这是我在这个论坛上的第一个问题。我希望我能正确描述我的问题。
我有一个名为 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
persons
不变;它仍然是相同的数组引用。但是您修改了数组内的对象,这是您不应该做的。你不能直接改变 React 中的状态,但它也不会检查你是否这样做了。
当您调用
setNewName
时,重新渲染将排队,并再次调用您的函数组件,这次使用修改后的对象来生成输出。