3

Im a react Noob(worked in angular quite a bit before),I have a question regarding refreshing a React Functional Child Component based on Input from a parent.

The Problem In this below example, Im trying to fetch some data from an promise and then passing them as props to a Child component. I initialize the child with a prop value "Fake Url 1" and replacing it with the value from the promise in useEffect(), which is the first Hook to be loaded once the component loads. But the child is not refreshing even though I changed the prop from parent.

What I tried 1) So Im changing the "props" of the child after the promise is complete. Shouldnt that re-render the child with new props ? (I thought props are similar to input and output in angular) 2) I did try to change the state of the parent and force a total reload, but that triggered an infinite loop, not sure why. The code which Im trying is ==> https://codepen.io/rohit2219/pen/mddPPaG

const { useEffect } = React;
const { useState } = React;

const Child = props => {
  let childUrl = props.url;

  //return (<div>{props.user}</div>)
  return <div>Child url : {childUrl}</div>;
};

const Parent = () => {
  let childData = "Fake Url 1";
  const [state, setState] = useState(false);

  useEffect(() => {
    childData = "Fake Url 2";
    let promise = axios.get(`https://api.github.com/users/mojombo`);
    promise.then(function(data) {
      console.log(data);
      childData = data.data.url;
      //setState(true) >> This state change triggered an infinite loop
      console.log("childData:");
    });
  });
  return (
    <div>
      <h1>Hello, World</h1>
      <Child url={childData} />
    </div>
  );
};

ReactDOM.render(<Parent />, document.getElementById("app"));

I did see many examples for doing that for a Class based React components like below, but nothing for functional components. Updating child's state from parent component

rohit2219
  • 218
  • 2
  • 12

1 Answers1

2

You should pass an empty array as dependency (in this case you should pass childData too) to useEffect to ensure the effect will only run once (componentDidMount) otherwise everytime setState is called a new render is triggered, calling the effect again and so on...

  useEffect(() => {
    childData = "Fake Url 2";
    let promise = axios.get(`https://api.github.com/users/mojombo`);
    promise.then(function(data) {
      console.log(data);
      childData = data.data.url;
      //setState(true) >> This state change triggered an infinite loop
      console.log("childData:");
    }, [childData])

childData isn't binded neither to state nor props it's just a let, React don't know how to react to changes on it.

const Component = () =>{
    const [childProp, setChildProp] = useState('foo')

    useEffect(() => setChildProp('bar'),[])

    return <Child childProp={childProp} />
}
Sefran2
  • 3,578
  • 13
  • 71
  • 106
Dupocas
  • 20,285
  • 6
  • 38
  • 56