React Hooks useCallback和备忘录列表重新渲染

时间:2019-12-07 09:39:17

标签: reactjs react-hooks

我是Hooks的新手,正在尝试使用Hooks创建等效的PureComponent版本。 我的目标是创建一个带有子组件的多选列表,该子组件负责呈现列表项:

const Movie: FunctionComponent<{
  title: string,
  score: number,
  id: number,
  isSelected: boolean,
  setSelected: React.Dispatch<React.SetStateAction<{}>>
  }> = React.memo(({ title, score, isSelected, setSelected, id }) => {

  const selectMovie = (): void => {
    if (isSelected === null)
      return;
    setSelected(id);
  };

  const selected = {
    backgroundColor: "blue"
  }

  console.log("render movie")

  return (
    <div onClick={selectMovie} style={isSelected ? selected : {}}>
      {title}, {score}
    </div>
  )
})

父组件具有数据以及选择的逻辑:

const App: FunctionComponent = () => {
  const data = [
    {
      id: 1,
      title: "Pulp fiction",
      score: 9
    },
    {
      id: 2,
      title: "Heat",
      score: 8
    },
    {
      id: 3,
      title: "American pie",
      score: 7
    }
  ]
  const [selectedItems, setSelected] = React.useState<{}>({});

  const selectMovie = React.useCallback((id: any) => {

    const sel: any = {...selectedItems};

    if (sel.hasOwnProperty(id)) {
      delete sel[id]
    } else {
      sel[id] = true;
    }

    setSelected(sel);
  }, [selectedItems])

  return (
    <div>
      {
        data.map(e => <Movie key={e.id} {...e} setSelected={selectMovie} isSelected={selectedItems.hasOwnProperty(e.id)}/>)
      }
    </div>
  )
}

我制作了一个沙箱,您可以在其中进行尝试:https://codesandbox.io/s/old-sun-38n4u

选择状态在对象的父组件中维护,并作为布尔值提供给子组件。问题是,当我单击电影时,所有3个列表项都会重新呈现(您可以在控制台中看到日志)。我也使用了React.memouseCallback来避免重新创建箭头函数以进行道具比较。我对钩子还很陌生,所以它一定有点愚蠢,我忽略了……

1 个答案:

答案 0 :(得分:1)

这是因为由于selectedItems依赖项的更改,您的selectMovie每次都在更改。

setSelected函数也可以使用一个函数,并且可以获取selectedItems值,因此无需将其设置为依赖项

Here is the working sandbox