因此,在典型的编程方案中,如果您对一个对象进行突变,则它会在任何地方对对象进行突变。但是,在React中,由于状态是不可变的并且只能通过每个组的集合*进行更改,因此,如果状态彼此嵌套(如下面所示的情况),则只有currentMember的名称会更改,而currentTeam或team中currentMember的版本不会更改。我必须逐一检查并逐个进行变异,这很麻烦。
一次改变多个状态或达到类似效果的最佳方法是什么?我已经通过建立索引来做到这一点,但是使用起来比较麻烦,而且我不知道是否有教科书挂钩可以解决此问题。
import React, { useState } from 'react'
interface Member {
name: string
}
interface Team {
name: string
members: Member[]
}
export default (props: {}) => {
const [teams, setTeams] = useState<Team[]>([
{
name: 'Team One',
members: [{ name: 'Wyatt' }, { name: 'Michael' }]
}
])
const [currentTeam, setCurrentTeam] = useState<Team>(teams[0])
const [currentMember, setCurrentMember] = useState<Member>(currentTeam.members[0])
return (
<>
<h1>${currentMember.name}</h1>
<button onClick={() => setCurrentMember(currentMember => { ...currentMember, name: 'Zach' })}>
Change current member name to Zach!
</button>
</>
)
}
答案 0 :(得分:1)
如上所述,通过这种方式使用状态会使事情变得有些复杂。您应该有一个包含所有团队的基本状态,然后按索引引用对您来说很重要的位。
例如,您的teams
状态很好。您的currentTeam
和currentMember
状态应该是要映射到teams
中的状态的索引或其他引用。
因此,按照特定的术语,我将在此处更改代码的格式(请原谅我,因为我没有编写TypeScript,所以我将使用纯正的Javascript以避免产生拼写错误):
import React, { useState } from 'react'
// interface Member {
// name: string
//}
// interface Team {
// name: string
// members: Member[]
//}
export default (props: {}) => {
const [teams, setTeams] = useState([
{
name: 'Team One',
members: [{ name: 'Wyatt' }, { name: 'Michael' }]
}
])
const [currentTeamIndex, setCurrentTeam] = useState(0)
const [currentMemberIndex, setCurrentMember] = useState(0)
return (
<>
<h1>${teams[currentTeamIndex].members[currentMemberIndex]}</h1>
<button onClick={() => setTeams(teams => ({
// Shallow copy the teams via mapping through them
...teams.map((team, teamIndex) => {
// If the current team index isn't the index we're on right now, then just
// return the existing team in its given place.
if (teamIndex !== currentTeamIndex) return team
// If we're at this point, it means the teamIndex matches the currentTeamIndex
// and we need to mutate this. We'll just do that by returning a new object
return {
...team, // Make sure we don't miss anything
...members.map((member, memberIndex) => {
// Same as the outer map, if the current member index isn't the same as the
// given memberIndex, then just return the member we're on, we're not mutating it
if (memberIndex !== currentMemberIndex) return member
return {
...member,
name: 'Zach'
}
})
}
}
})
>
Change current member name to Zach!
</button>
</>
)
}
如您所见,将对象深入到对象并不是那么简单,但是可以在不更改原始数据的情况下进行操作-您可以通过使用Array函数动态重建数据来完成所需的操作,传播语法和索引引用。
您可能还想考虑将其限制在化简器中,并通过包含团队ID索引和成员ID索引的特定操作来使它更具可组合性。