29

Ok so:

  useEffect(() => {
    
  }, [props.lang]);

What should I do inside useEffect to rerender component every time with props.lang change?

Piotr Żak
  • 2,046
  • 5
  • 18
  • 30

3 Answers3

35

Think of your useEffect as a mix of componentDidMount, componentDidUpdate, and componentWillUnmount, as stated in the React documentation.

To behave like componentDidMount, you would need to set your useEffect like this:

  useEffect(() => console.log('mounted'), []);

The first argument is a callback that will be fired based on the second argument, which is an array of values. If any of the values in that second argument change, the callback function you defined inside your useEffect will be fired.

In the example I'm showing, however, I'm passing an empty array as my second argument, and that will never be changed, so the callback function will be called once when the component mounts.

That kind of summarizes useEffect. If instead of an empty value, you have an argument, like in your case:

 useEffect(() => {

  }, [props.lang]);

That means that every time props.lang changes, your callback function will be called. The useEffect will not rerender your component really, unless you're managing some state inside that callback function that could fire a re-render.

UPDATE:

If you want to fire a re-render, your render function needs to have a state that you are updating in your useEffect.

For example, in here, the render function starts by showing English as the default language and in my use effect I change that language after 3 seconds, so the render is re-rendered and starts showing "spanish".

function App() {
  const [lang, setLang] = useState("english");

  useEffect(() => {
    setTimeout(() => {
      setLang("spanish");
    }, 3000);
  }, []);

  return (
    <div className="App">
      <h1>Lang:</h1>
      <p>{lang}</p>
    </div>
  );
}

Full code:

Edit heuristic-rubin-pmdjk

Bonifacio2
  • 3,405
  • 6
  • 34
  • 54
Elder
  • 1,475
  • 9
  • 17
  • 1
    I understand the concept of second argument. I need a rerender component after props.lang change. How can I managing some state with callback function? – Piotr Żak Sep 20 '19 at 08:34
  • 1
    e.g How fire re-render? – Piotr Żak Sep 20 '19 at 10:01
  • @PiotrŻak Check my updated answer, see if that helps somehow. – Elder Sep 20 '19 at 16:46
  • Hey - I pass to RenderExplore props.lang. It's eng or pl, and it's change, when user call action. I need a rerender whole component, because i have layer of animation, and after lang change it's need to rerender to work well – Piotr Żak Sep 21 '19 at 17:06
  • How can I mount and unmount component after second argument in useEffect change? – Piotr Żak Sep 21 '19 at 17:06
  • When we use useEffect(() => { }, []); its execute one Times, But useEffect(() => { }, [state]) execute each time that state will change – hamid reza Heydari Mar 21 '23 at 07:58
9

Simplest way

Add a dummy state you can toggle to always initiate a re-render.

const [rerender, setRerender] = useState(false);

useEffect(()=>{

    ...
    setRerender(!rerender);
}, []);

And this will ensure a re-render, since components always re-render on state change.

You can call setRerender(!rerender) anywhere anytime to initiate re-render.

Abraham
  • 12,140
  • 4
  • 56
  • 92
0
const [state, set] = useState(0);

useEffect(() => {
  fn();
},[state])

function fn() {
  setTimeout((), {
    set(prev => prev + 1)
  }, 3000)
}

The code above will re-render the fn function once every 3 seconds.

  • 1
    Extremely bad practice. You wouldn't want set a timer to refresh page based on increments; you should instead, use events (like a state change) to re-render a page. If this re-render occurred as a high level component, you'll unnecessarily re-render children components and cause major performance issues. Essentially, this solution may work, but isn't scalable for professional applications. – G M Dec 03 '22 at 04:07
  • the code above will let you understand how re render function works not use it in "profesional applications" – Nivek Mozart Dec 05 '22 at 07:08