如何避免React Hook UseState共享状态?

时间:2019-07-26 01:31:19

标签: reactjs react-hooks

这个问题的标题可能不好,但这是我的情况。

我使用json块来呈现列表。列表项可以展开,并显示具有子属性的子列表。 json结构包含两个数组,每个数组包含更多子数组。我使用标签来切换阵列。

我使用useState来管理每个单独的子数组组件的值isExpanded。但似乎状态isExpaned已为所有标签共享。

即使切换到另一个选项卡,状态isExpanded仍保持不变。换句话说,为什么当我切换到另一个标签时,子列表会保持展开状态?

此外,为什么每个选项卡的扩展子列表彼此重叠。当我切换到另一个选项卡时,它们应该保持“关闭”状态,因为我已经将初始状态设置为false。 (const [isExpand, setIsExpand] = useState(false)

const ListItem = ({name, children}) => {
  const [subList, setSubList] = useState(null)
  const [isExpand, setIsExpand] = useState(false)
  const handleItemClick = () => {
    children && setIsExpand(!isExpand)
    console.log(isExpand)
  }
  useEffect(() => {
    isExpand && children && setSubList(children)
  }, [isExpand, children])
  return (
    <div className='list-wrapper'>
      <div className='list-item'>
        {name}
        {
          children && 
          <span 
            className='expand' 
            onClick={() => handleItemClick()}>
            {isExpand ? '-' : '+'}
          </span>
        }
      </div>
      <div className='list-children'>
        {
          isExpand && subList && subList.map((item, index) => 
            <ListItem key={index} name={item} />
          )
        }
      </div>
    </div>
  )
}

这是codesanbox,有人帮忙吗?

1 个答案:

答案 0 :(得分:1)

由于index被用作ListeItem键,因此React似乎很困惑。
(React会尝试“共享” isExpanded状态,因为根据您指定的键它们看起来相同)

您可以从key={index}更改密钥

   <div className="contents">
      {contents &&
        contents.children &&
        contents.children.map((item, index) => (
          <ListItem
            ...... ? ....
            key={index}
            name={item.name}
            children={item.children}
          />
        ))}
    </div>

使用更独特的键item.name

   <div className="contents">
      {contents &&
        contents.children &&
        contents.children.map(item => (
          <ListItem
            ...... ? ....
            key={item.name}
            name={item.name}
            children={item.children}
          />
        ))}
    </div>

查看分叉的沙箱。
https://codesandbox.io/s/soanswer57212032-9ggzj