1

During the conversion of class components to functional component with hooks, I came across a scenario which I will try to recreate with a simple example:

I have

  • Parent component as class component ParentClass
  • Child component as a functional component with hooks ChildComponent

My parent component ParentClass passes an inline arrow function to ChildComponent as a prop

parent.jsx (which is a class component)

// inside render method
render () {
  return (
    <div>
    {
      ["component1", "component2"].map((c) => (
        <ChildComponent
          key={c}
          setParentItem={
            (item) => {
              // ... some more logics involving values available in
              // curernt scope only. (for example c)
              this.setState({
                component: c,
                item,
              });
            }
          }
        />
      ))
    }
    </div>
  )
}

child.jsx (which is a functional component)

const [selectedItem, setSelectedItem] = useState({});

/**
  * Here in the dependency array of useEffect
  * eslint-plugin-react asks to add setParentItem as dependency
  * which should be memoized because from the parent component it is
  * passed as an inline arrow function.
  * How can I resolve this?
  */
useEffect(() => {
  setParentItem(selectedItem);    // setParentItem retrieved via props from ParentClass component
}, [selectedItem]);    // Here; adding setParentItem in dependency array will cause infinite render

How can I memoize setParentItem so that after adding it to the dependency array of useEffect in the ChildComponent, render will not get stuck in an infinite loop?

Please also have a look at the codesandbox for working example.

1 Answer 1

1

Add it as field of the class component:


class MyComponent extends React.Component {
  setParentItem = () => {
    // ...
  }

  render() {
    // ...

    <ChildComponent
          setParentItem={this.setParentItem}
    />

    // ...
  }
}

Now, when your callback use closures you cant do it that simply. In this case you have to change your code so it doesn't create closures. I.e. make ChildComponent to forward value:


function ChildComponent({ setParentItem, component, ...props }) {
  // ...
  setParentItem(selectedItem, component);
}

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.