0

New to react hook world, trying to learn by coding, i'm not sure about this componentDidUpdate to where put it inside useEffect any suggestions ? this is my code:

componentDidMount() {
  if (!this.props.realGraph) {
    this.loadGraph();
  }
  
  this.refs.graphDiv.addEventListener("click", this.onClickGraphDiv, true);
}

discardGraph() {
  this.props.clearGraphData();
  this.loadGraph();
}

componentDidUpdate() {
  this._zoomConfig();
}

_zoomConfig = () => {
  const z = d3Select(`#graph-id-graph-wrapper`)
  .call(d3Zoom())
  .on("dblclick.zoom", null)
  .on("mousedown.zoom", null)
};

realGrpah comes from mapStateToProps

this is what i have done converting it to hooks,

useEffect(() => {
  if (!props.realGraph) {
    loadGraph();
  }
  
  refs.graphDiv.addEventListener("click", onClickGraphDiv, true);
  _zoomConfig();
}, []);


discardGraph() {
  props.dispatch(clearGraphData())
  loadGraph();
}

_zoomConfig = () => {
  const z = d3Select(`#graph-id-graph-wrapper`)
  .call(d3Zoom())
  .on("dblclick.zoom", null)
  .on("mousedown.zoom", null)
};
zhulien
  • 5,145
  • 3
  • 22
  • 36
waleedd32
  • 473
  • 2
  • 9
  • 23
  • See [React Documentation](https://reactjs.org/docs/hooks-reference.html#useeffect) [A great video about useEffect - Youtube](https://www.youtube.com/watch?v=j1ZRyw7OtZs) and [inDepth stackOverflow answer on using useEffect](https://stackoverflow.com/questions/59841800/react-useeffect-in-depth-use-of-useeffect/59841947#59841947) – Shivam Jha Aug 01 '21 at 15:42
  • [This](https://www.codegrepper.com/code-examples/javascript/react+functional+component+unmount) can help you understand your scenario. – Tushar Walzade Aug 01 '21 at 15:42

2 Answers2

2

You can use a separate effect that fires on every re-render:

// Approximately component did mount
useEffect(() => {
  if (!props.realGraph) {
    loadGraph();
  }  
  refs.graphDiv.addEventListener("click", onClickGraphDiv, true);
}, []);

// Approximately component did update
useEffect(() => {
  _zoomConfig();
})

Now if you don't want it to fire on the first render, you can create a ref to a boolean that you use to ignore the initial mounting, which I believe would be more analogous to componentDidUpdate:

// Approximately component did mount
useEffect(() => {
  if (!props.realGraph) {
    loadGraph();
  }  
  refs.graphDiv.addEventListener("click", onClickGraphDiv, true);
  _zoomConfig();
}, []);

// Approximately component did update
const isMounted = useRef(false);
useEffect(() => {
  if (!isMounted.current) {
    isMounted.current = true;
  } else {
    _zoomConfig();
  }
})
Nick
  • 16,066
  • 3
  • 16
  • 32
  • so this will do it also : useEffect(() => { if (!props.realGraph) { loadGraph(); } refs.graphDiv.addEventListener("click", onClickGraphDiv, true); }, []); useEffect(() => { _zoomConfig(); }) ? – waleedd32 Aug 01 '21 at 15:47
  • Yes, you can have two effects in the same component – Nick Aug 01 '21 at 15:48
  • I have updated the answer to make it clearer that you can have multiple effects – Nick Aug 01 '21 at 15:49
  • what is the difference between my version which is one useEffect and yours where is two ? i mean functionality – waleedd32 Aug 01 '21 at 15:54
  • Your version has an empty dependency array, which is the second argument you're passing to the `useEffect` function. Since the dependency array is empty, it will only run on component mount and never again. When there's _no_ dependency array, it will run on every render. When there are variables in the dependency array, it'll run every time one of those variables changes. – Nick Aug 01 '21 at 17:05
0

I'm also not a super expert in react, but following solution might be useful for your scenario -

For DidMount, the use case is very straightforward -

useEffect(() => {
    // your code
}, []); // passing an empty dependency array will fire it only for the first time when component renders

For achieving DidUpdate, You can pass a prop from your parent component to your current component & fire an effect on updation of that prop as follows -

for example, you've used this component in parent component as -

const [updateZoom, setUpdateZoom] = useState(0);    // using this to update child component

// handleZoom on some event
const handleZoom = () => {
    setUpdateZoom(uz => uz + 1);
}

return (
    <GraphComponent realGraph={realGraph} clearGraphData={clearGraphData} updateZoom={updateZoom} />
);

And use updateZoom in your current/ child component as follows -

useEffect(() => {
    console.log('updateZoom did update');
    this._zoomConfig();
}, [updateZoom]);
Tushar Walzade
  • 3,737
  • 4
  • 33
  • 56