React“State Hook”在不使用 setState() 方法的情况下自动重新分配

问题描述 投票:0回答:1

这是我在这个论坛上的第一个问题。我希望我能正确描述我的问题。

我有一个名为 Person 的状态钩子:

const [persons, setPersons] = useState([])

我的目标是在发出 PUT 请求后重新渲染“persons”数组。我的代码按预期工作,但我不明白为什么即使我不使用 setPersons() 方法,“persons”数组也会自动重新分配。

if(window.confirm(`${newPerson.name} is already added to the phonebook, replace the old number with a new one?`))
      {
        console.log('update person:',newPerson)
        personsService.updatePerson(newPerson)
                      .then(response => console.log(`${response.name}'s number has been updated`))
           
        //update persons list locally  
        persons.map(person=>{
          person.id === newPerson.id ? person.number = newPerson.number : person //why does this code work without setPersons??
        })
       //when I don't use this map function, the array doesn't get automatically re-assigned

提前致谢!

我的完整代码:

import { useState, useEffect } from 'react'
import Filter from './components/Filter'
import PersonForm from './components/PersonForm'
import Persons from './components/Persons'
import personsService from './services/persons'

const App = () => {
  const url = 'http://localhost:3001/persons'
  const [persons, setPersons] = useState([])
  //useEffect is executed after all components have been rendered
  //this is why console.log("Execute the other codes...") was executed before console.log("fetching data from the server...")
  //despite the code order
  useEffect(()=>{
    console.log("fetching data from the server...")
    personsService.getPersons()
      .then(response=>{
        console.log("Data have been fetched successfully!")
        console.log("Data: ", response)
        console.log("Update Persons state...")
        setPersons(response)
    })
  },[])

  console.log("Execute the other codes...")

  console.log("Initial state of persons state is: ",persons)
  const [newName, setNewName] = useState('')
  const [telNumber, setTelNumber] = useState('')
  const [filter, setFilter] = useState('')
  
//Event handler
  const onChangeHandler = (event) =>{
    setNewName(event.target.value)
  }

  const deleteHandler = (id,name) =>{
    console.log('Auaaa',id)
    if(window.confirm(`Delete ${name}?`))
    {
      personsService.deletePerson(id)
      const arrayAfterDeletion = persons.filter(person=>person.id !== id)
      setPersons(arrayAfterDeletion)
      
      
    }

  }


  const telChangeHandler = (event) =>{
    setTelNumber(event.target.value)
  }

  const filterChangeHandler= (event) =>{
    setFilter(event.target.value)
  }

  const onClickHandler = (event)=>{
    event.preventDefault()
    const newPerson = {id:newName, name:newName, number:telNumber} 

    //check persons list, whether it contais the same person (same name & number)
    let containsTheSamePerson = false
  
    persons.forEach(person=>{
      //doesn't make sense here if we compare the objects (always different because the id)
      if(person.name === newPerson.name)
      {
        containsTheSamePerson = true
      }

    })

    if(!containsTheSamePerson)
    {
      const newPersonList = persons.concat(newPerson)
      //console.log('old list', persons)
      //console.log('new list',newPersonList);
      setPersons(newPersonList)

      //push new person to the server
      personsService.addNewPerson(newPerson)
                  .then(response => console.log(`${response.name} has been added to database`))
    
      setNewName('')
      setTelNumber('')
    }else{
      //alert(`${newPerson.name} is already added to the phonebook`)
      if(window.confirm(`${newPerson.name} is already added to the phonebook, replace the old number with a new one?`))
      {
        console.log('update person:',newPerson)
        personsService.updatePerson(newPerson)
                      .then(response => console.log(`${response.name}'s number has been updated`))
           
        //update persons list locally  
        persons.map(person=>{
          person.id === newPerson.id ? person.number = newPerson.number : person //why does this code work withour setPersons??
        })
        
      
        setNewName('')
        setTelNumber('')

      }
    }
  }

  return (
    <div>
      <h2>Phonebook</h2>
      <Filter value = {filter} onChangeHandler = {filterChangeHandler}/>
      <h3>Add a new</h3>
     
      <PersonForm nameValue={newName} nameChangeHandler={onChangeHandler} 
                  numValue={telNumber} numChangeHandler={telChangeHandler} 
                  buttonHandler={onClickHandler}/>
      <h2>Numbers</h2>
      <Persons list = {persons} filter = {filter} onClickDelete={deleteHandler}/>
    </div>
  )
}

export default App
reactjs react-hooks axios jsx put
1个回答
0
投票

persons
不变;它仍然是相同的数组引用。但是您修改了数组内的对象,这是您不应该做的。你不能直接改变 React 中的状态,但它也不会检查你是否这样做了。

当您调用

setNewName
时,重新渲染将排队,并再次调用您的函数组件,这次使用修改后的对象来生成输出。

© www.soinside.com 2019 - 2024. All rights reserved.