2

I'm new to Hooks and trying to create a PureComponent equivalent version with Hooks. My goal is to create a multiselectable list with a child component that is reponsible for rendering the list items:

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>
  )
})

The parent component have the data as well as the logic for the selection:

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>
  )
}

I made a sandbox where you can try it out: https://codesandbox.io/s/old-sun-38n4u

The selection state is maintained in the parent component in an object and supplied to the child as a boolean. The problem is when I click on a movie all 3 list items re-renders (you can see the log in the console). I have used React.memo and useCallback as well to avoid arrow function re-creation for the props comparison. I'm pretty new to hooks, so it must be something silly I'm overlooking...

1 Answer 1

2

That is because your selectMovie is changing every time due to selectedItems dependency changing.

setSelected function can also take a function and you can get the selectedItems value so you don't need to set it as a dependency

Here is the working sandbox

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.