20210916 - Cannot read property 'name' of null
2021-09-16 00:00:00

起因:

做phonebook的时候发现一个bug:后端新建一个联系人,前端刷新,更新最新的phonebook,并返回后端删除刚刚新建的联系人,前端修改这个联系人(实际上数据库中已经不存在)的信息,submit后报如下错误:

Untitled

前端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const samePerson = persons.find(person => person.name === newName)
const changedPerson = {...samePerson, number: newNumber}

personService
.update(samePerson.id, changedPerson)
.then(returnedPerson => {
**console.log(returnedPerson) // Debug**
setPersons(persons.map(person => person.id === samePerson.id ? returnedPerson : person))
setNewName('')
setNewNumber('')
setError(false)
setMessage(
`Updated ${returnedPerson.name}'s number`
)
setTimeout(() => {
setMessage(null)
}, 5000)
})
.catch(error => {
setMessage(
`Information of ${samePerson.name} has already been removed from server`
)
setTimeout(() => {
setMessage(null)
}, 5000);
setPersons(persons.filter(person => person.name !== newName))
setError(true)
})

修改前的后端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.put('/api/persons/:id', (req, res, next) => {
const body = req.body
const person = {
name: body.name,
number: body.number,
}

Person.findByIdAndUpdate(req.params.id, person, {new: true})
.then(updatedPerson => {
**console.log(updatedPerson) // Debug**
res.json(updatedPerson)
})
.catch(error => next(error))
})

先debug前端代码,发现接收到的put请求的返回值returnedPerson 为null,按理说这种情况promise应该rejected,进入catch,并且输出报错的message。

debug后端代码,发现更新数据后返回的updatedPerson 也为null,于是加了个判断,不为null就返回,为null就报错,返回给前端就是rejected,进入catch,并输出报错的message。

修改后的后端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
app.put('/api/persons/:id', (req, res, next) => {
const body = req.body
const person = {
name: body.name,
number: body.number,
}

Person.findByIdAndUpdate(req.params.id, person, {new: true})
.then(updatedPerson => {
console.log(updatedPerson)
if (updatedPerson) {
res.json(updatedPerson)
} else {
res.status(404).end()
}
})
.catch(error => next(error))
})

React App可以正常运行

Untitled

这个情况和之前在GET请求中用findByID() 获取单个document很相似,那个案例中也是对返回值作了判断,如果是id合法但未找到信息(被删除或者本来就不存在),就返回null(没测试过,但理论上应该是这样),而id不合法直接进入catch返回error。所以大概是mongoose的findXXX方法的特性??

20210915 - 两种情况两种状态码

另(这是我发现这个错误之前的前端代码):

这段代码让我疑惑的点是,为什么在setNewName('')之后,setMessage()仍然可以获得newName的值?之前写的时候竟然没注意到。。。

(关于这个,听过一种说法是,多个setState的时候,可能会组团一起更新。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
personService
.update(samePerson.id, changedPerson)
.then(returnedPerson => {
console.log(returnedPerson)
setPersons(persons.map(person => person.id === samePerson.id ? returnedPerson : person))
setNewName('')
setNewNumber('')
setError(false)
setMessage(
`Updated ${**newName**}'s number`
)
setTimeout(() => {
setMessage(null)
}, 5000)
})
.catch(error => {
setNewName('')
setNewNumber('')
setMessage(
`Information of ${**newName**} has already been removed from server`
)
setTimeout(() => {
setMessage(null)
}, 5000);
setPersons(persons.filter(person => person.name !== newName))
setError(true)
})

贴一下相关的问答和参考:

为什么调用react setState方法不会立即改变状态?

React Lifecycle Methods diagram

React.Component - React

React setState not Updating Immediately