user8758206
user8758206

Reputation: 2191

Forcing a react functional component to trigger a rerender

I'm trying to get a functional component to force a rerender whenever the testFn executes. I thought to use state to do this (if there's a better way then please speak up), which appears to successfully force a rerender but only twice, then nothing.

I built a simple demo to emulate the issue as using my real app is too difficult to demonstrate but the same principles should presumably apply (my real demo fetches data when the function executes and displays it on the page, but it's not rerendering and I have to refresh the page to see the new data, hence why I want to trigger a rerender).

import React, { useState } from "react";

const App = () => {
  const [, rerender] = useState(false);

  const testFn = () => {
    console.log("test Fn");
    rerender(true);
  };

  return (
    <div>
      <p>test</p>
      <button onClick={testFn}>clickk</button>
      {console.log("render")}
    </div>
  );
};

export default App;

I've also made a Stackblitz demo for conveinence.

Can anyone solve this demo or think of a better way of implementing it?

Thanks for any help here.

Upvotes: 6

Views: 13968

Answers (3)

Arnold_Sanders
Arnold_Sanders

Reputation: 150

I've had this same question. I've found that you could also pass down a function into a child component. Watch for a state change of the function from the parent component with a useEffect. And when the function is invoked in the child component, it will force a rerender in the parent component for the child component.

Upvotes: 0

Quentin
Quentin

Reputation: 944530

It triggers a re-render when the state changes.

The first time you click the button you change the state from false to true so a rerender is triggered.

Subsequent clicks you change it from true to true which isn't a change, so it doesn't.

You could toggle it:

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

and

rerender(!render);

so it actually changes.

… but this smells of being an XY Problem, and you should probably be changing something which is actually being rendered.

Upvotes: 9

CertainPerformance
CertainPerformance

Reputation: 371193

State is the right way, since state changes are the primary way to cause re-renders. I'd increment a counter:

const [, setCount] = useState(0);
// force a re-render by running:
setCount(c => c + 1)

But this is still a very odd thing to do. In almost all cases, a much more elegant solution will be implementable, such as by putting data that changes into state, and calling the state setter when the data updates.

Upvotes: 6

Related Questions