Can you force a React component to rerender without calling setState?
Asked Answered
W

23

1099

I have an external (to the component), observable object that I want to listen for changes on. When the object is updated it emits change events, and then I want to rerender the component when any change is detected.

With a top-level React.render this has been possible, but within a component it doesn't work (which makes some sense since the render method just returns an object).

Here's a code example:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

Clicking the button internally calls this.render(), but that's not what actually causes the rendering to happen (you can see this in action because the text created by {Math.random()} doesn't change). However, if I simply call this.setState() instead of this.render(), it works fine.

So I guess my question is: do React components need to have state in order to rerender? Is there a way to force the component to update on demand without changing the state?

Waine answered 3/6, 2015 at 16:44 Comment(5)
the accepted answer says this.forceUpdate() is the right solution whereas rest of all answers and several comments are against using forceUpdate(). Will that then be fine to say that the question didn't get a proper solution/answer yet?Granite
The excepted answer answered my question at the time. Is is technically the answer I was looking for, and I still think the right answer. The other answers I think are good supplemental information for folks with the same question to be aware of.Waine
Interesting to note is that you DON'T NEED ANYTHING IN STATE at all other than initializing it to a plain object, then calling this.setState({}) just triggers a new render. React is great but also weird sometimes. Therefore you could directly loop through a stores data when trigger a change without extra plumbing or worry about data per component instance.Indefectible
On the whole I would say yes. If you are using force update this is for updating components where they may be dependent on changes outside of the state management of your app. I cannot think of a good example of that. Useful to know though.Sitnik
Why would you even need to do this? -- it's wrong logic in your app!!!!Remittee
U
1056

In class components, you can call this.forceUpdate() to force a rerender.

Documentation: https://facebook.github.io/react/docs/component-api.html

In function components, there's no equivalent of forceUpdate, but you can contrive a way to force updates with the useState hook.

Umbel answered 3/6, 2015 at 16:47 Comment(9)
Another way is this.setState(this.state);Speleology
Using forceupdate is discouraged, please see the last answer.Teammate
While this.forceUpdate() isn't a very good solution to the askers' problem, it's the correct answer to the question posed in the title. While it should generally be avoided, there are situations when forceUpdate is a good solution.Despond
@Speleology Actually, additional logic can be implemented in shouldComponentUpdate() rendering your solution futile.Uppercut
Maximum call stack size exceededRf
Error: Possible Unhandled Promise Rejection (id: 0): _this2.forceUpdate is not a functionBiased
@zulkarnainshah a stateless functional component does not have 'this' attached. If you want to use forceUpdate, then you'll need to turn your component into a class.Tradeswoman
setState() is asynchronous. And that's why in some cases it doesn't work very well.Appanage
@JasonMcCarrell No, there are certain cases where forceUpdate() is useful. If it were really so bad, it wouldn't be part of the API in the first place.Icken
S
439

forceUpdate should be avoided because it deviates from a React mindset. The React docs cite an example of when forceUpdate might be used:

By default, when your component's state or props change, your component will re-render. However, if these change implicitly (eg: data deep within an object changes without changing the object itself) or if your render() method depends on some other data, you can tell React that it needs to re-run render() by calling forceUpdate().

However, I'd like to propose the idea that even with deeply nested objects, forceUpdate is unnecessary. By using an immutable data source tracking changes becomes cheap; a change will always result in a new object so we only need to check if the reference to the object has changed. You can use the library Immutable JS to implement immutable data objects into your app.

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.forceUpdate()

Changing the key of the element you want re-rendered will work. Set the key prop on your element via state and then when you want to update set state to have a new key.

<Element key={this.state.key} /> 

Then a change occurs and you reset the key

this.setState({ key: Math.random() });

I want to note that this will replace the element that the key is changing on. An example of where this could be useful is when you have a file input field that you would like to reset after an image upload.

While the true answer to the OP's question would be forceUpdate() I have found this solution helpful in different situations. I also want to note that if you find yourself using forceUpdate you may want to review your code and see if there is another way to do things.

NOTE 1-9-2019:

The above (changing the key) will completely replace the element. If you find yourself updating the key to make changes happen you probably have an issue somewhere else in your code. Using Math.random() in key will re-create the element with each render. I would NOT recommend updating the key like this as react uses the key to determine the best way to re-render things.

Splice answered 25/1, 2016 at 23:58 Comment(19)
I'd be interested to know why this got a downvote? I've been banging my head trying to get screen readers to respond to aria alerts and this is the only technique I've found that works reliably. If you have something in your UI that generates the same alert each time it is clicked, by default react doesn't re-render the DOM so the screen reader doesn't announce the change. Setting a unique key makes it work. Maybe the downvote was because it still involves setting state. But forcing a re-render to DOM by setting key is golden!Swatch
I very much liked this answer because - 1: use of forceupdate() is discouraged, and 2: this way is very helpful for 3rd party components which you have installed via npm, meaning not your own components. E.g React-resizable-and-movable is a 3rd party component that I use, but it's not reacting to my component setstate. this is great solution.Teammate
Won't changing a key remove old html nodes and create new ones?Uppercut
Moreover, additional logic can be implemented in shouldComponentUpdate() rendering your solution futile.Uppercut
@Uppercut key allows for reordering nodes for speed (skipping remove/add), but AFAIK if there's no candidate it'll change the existing node instead of doing a complete remove/addPigheaded
@Uppercut But yes, using key isn't good for this example, since OP was just outputting the value, not doing anything fancy like thatPigheaded
This is a hack and an abuse of key. First, it's intent is unclear. A reader of your code will have to work hard to understand why you are using key this way. Second, this is no more pure than forceUpdate. "Pure" React means that the visual presentation of your component is 100% dependent on its state, so if you change any state, it updates. If however, you have some deeply nested objects (the scenario the forceUpdate docs cite a reason to use it) then using forceUpdate makes that clear. Third, Math.random() is…random. Theoretically, it could generate the same random number.Katykatya
@xtraSimplicity I can't agree that this complies with the React way of doing things. forceUpdate is the React way of doing this.Jennifferjennilee
@Robert Grant, looking back, I agree. The added complexity isn't really worth it.Beacon
It is a useful solution in certain cases, especially if you can tie key uniquely to the data. I rarely have to use this stuff outside of things like charts (which compose with a lot of deeply nested elements), but it's useful when I need to do so—e.g. not Math.random() but key tied to a unique index for the data that forces a rerender.Octaviaoctavian
Its been some time since I answered this question. The only case in which I've needed to randomize the key lately was using the beta react hot module loader, but it was more of a hack than anything. The immutable part of this answer holds true. Your components should react to updates to your data. I've found most of the time when using redux I can eliminate state all together and use pure components that will be updated when the data in their props change. And that data is passed as props by using the connect function from the react-redux package.Splice
I would like to add a practical usecase in which I think forceUpdate is okay, but please correct me if I missed any options: I have a container which needs to perform an update on itself (translate style) after all child nodes have been mounted and interrogated for their width (which is set via stylesheet and outside of my control). In this case, this.setState(this.state); would not be idiomatic as nothing in the state has changed and I only require to re-run render(). Please correct me if I'm wrong.Stoical
@Stoical I think passing in the translate values as props or using the components state for the translate values would be a better way to do it, but if you are translating a value via css - i don't see why you would need to use forceUpdateSplice
@realseanp That was an option I had considered, but the translate value is a something I don't want the rest of the app to be concerned with. Instead the app passes in the item to be focused, the component renders, interrogates all its refs to calculate the proper offsets, and then forces a re-render to update to the correct position. The child dimensions (to my last tests), are only available after render has already run. Since no state has changed to the rest of the app, I thought forceUpdate would be more idiomatic not to use this.setState(...) method.Stoical
@Katykatya I was of the same opinion as you, however, surprisingly react docs approve and even recommend this method in some cases: reactjs.org/blog/2018/06/07/…Darg
math.random() does create issue in safari.Flimflam
I was going to upvote for the changing the key suggestion - brilliant - until I saw the editorial. A VERY good legitimate reason to force an update is when you have an entrance animation. I'm sure there are others.Barbee
@PeterMoore yeah another reason may be when you want to re-render a component thus ensuring all life cycle methods/hooks run from a fresh state.Splice
yeah just make sure your redux assets' reference objects are using spread to create a new reference. redux/react doesn't always notice an updated object/array w the same reference. your components local state should be fine as state objects are immutable (non changeable, they are created new each time by react using setState in class or hooks in functional) but if you have a saga or action updating state, create a new reference with spread. this will probably fix som of OP's issues related to state.Angst
C
189

In 2021 and 2022, this is the official way to forceUpdate a React Functional Component.

const [, forceUpdate] = useReducer(x => x + 1, 0);

  function handleClick() {
    forceUpdate();
  }

I know the OP is for a class component. But the question was asked in 2015 and now that hooks are available, many may search for forceUpdate in functional components. This little bit is for them.

Edit 18th Apr 2022

It's usually bad practice to force update your components.

A few reasons that can cause the need to use force updates.

  • Not using state variables where you have to - local, redux, context.
  • The field from the state object you are trying to access and expecting to update/change is too deeply nested in objects or arrays. Even Redux advises to maintain flat objects or arrays. If only one field value changes in a complex object, React may not figure out that the state object has changed, thus it does not update the component. Keep your state flat and simple.
  • The key on your list items, as mentioned in another answer. In fact, this can cause other unexpected behaviors as well. I've seen lists where items are repeatedly rendered (duplicates) because the keys aren't identical or the keys are just missing altogether. Always request the backend team to send unique ids everywhere possible! Avoid using array indexes for keys. Do not try to create unique ids on the front-end by using nanoid, uuid or random. Because ids created using above methods change each time the component updates (keys provided to a list need to be static and the same on each render). Creating unique ids is usually a backend concern. Try your best to not bring that requirement to the front-end. The front-end's responsibility is only to paint what data the backend returns and not create data on the fly.
  • If your useEffect, useCallback dependency arrays do not have the proper values set. Use ESLint to help you with this one! Also, this is one of the biggest causes for memory leaks in React. Clean up your state and event listeners in the return callback to avoid memory leaks. Because such memory leaks are awfully difficult to debug.
  • Always keep an eye on the console. It's your best friend at work. Solving warning and errors that show up in the console can fix a whole lot of nasty things - bugs and issues that you aren't even aware off.

A few things I can remember that I did wrong. In case it helps..

Chur answered 2/3, 2021 at 9:15 Comment(2)
Keep in mind that it still says: "Try to avoid this pattern if possible".Getraer
@Getraer Yep, that's the case for all the answers to this question because you aren't supposed to forceUpdate. If you find yourself using any of the implementations of a forced update, it usually means you are doing something that is not the React way. Avoid forceUpdate as much as possible, unless you have to!Chur
U
119

Actually, forceUpdate() is the only correct solution as setState() might not trigger a re-render if additional logic is implemented in shouldComponentUpdate() or when it simply returns false.

forceUpdate()

Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). more...

setState()

setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate(). more...


forceUpdate() can be called from within your component by this.forceUpdate()


Hooks: How can I force component to re-render with hooks in React?


BTW: Are you mutating state or your nested properties don't propagate?

Uppercut answered 2/6, 2016 at 14:0 Comment(2)
one interesting thing to note is that state assingments outside of setState such as this.state.foo = 'bar' will not trigger the render lifecycle methodVespasian
@lfender6445 Assigning state directly with this.state outside of the constructor should also throw an error. Might not have done so in 2016; but, I am pretty sure it does it now.Damnable
E
52

I Avoided forceUpdate by doing following

WRONG WAY : do not use index as key

this.state.rows.map((item, index) =>
   <MyComponent cell={item} key={index} />
)

CORRECT WAY : Use data id as key, it can be some guid etc

this.state.rows.map((item) =>
   <MyComponent item={item} key={item.id} />
)

so by doing such code improvement your component will be UNIQUE and render naturally

Elfie answered 6/8, 2017 at 4:42 Comment(2)
this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )Wrasse
To justify my down vote, despite it is a good practice to use this approach, this answer is not related to the question.Lemos
C
42

When you want two React components to communicate, which are not bound by a relationship (parent-child), it is advisable to use Flux or similar architectures.

What you want to do is to listen for changes of the observable component store, which holds the model and its interface, and saving the data that causes the render to change as state in MyComponent. When the store pushes the new data, you change the state of your component, which automatically triggers the render.

Normally you should try to avoid using forceUpdate() . From the documentation:

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your application much simpler and more efficient

Customary answered 4/6, 2015 at 11:51 Comment(5)
What is the memory status of a component state? If I have five components on a page and they all are listening to a single store, do I have the data five times in memory, or are they references? And don't all of those listeners add up fast? Why is it better to "trickle down" than to just pass data to your target?Lily
Actually the recommendations are to pass the store data to component props and only use the component state for things like scroll state and other minor ui-specific things. If you use redux (I recommend it), you can use the connect function from react-redux to automatically map store state to component props whenever needed based on a mapping function you supply.Raina
@Lily the state would be assigned to a store's data which is just a pointer to it anyway so memory is not an issue unless you are cloning.Indefectible
"forceUpdate() should be always avoided" is incorrect. The documentation clearly says: "Normally you should try to avoid all uses of forceUpdate()". There are valid use cases of forceUpdateLafreniere
@Lafreniere you're absolutely right, that was personal bias speaking :) I have edited the answer.Customary
I
25

use hooks or HOC take your pick

Using hooks or the HOC (higher order component) pattern, you can have automatic updates when your stores change. This is a very light-weight approach without a framework.

useStore Hooks way to handle store updates

interface ISimpleStore {
  on: (ev: string, fn: () => void) => void;
  off: (ev: string, fn: () => void) => void;
}

export default function useStore<T extends ISimpleStore>(store: T) {
  const [storeState, setStoreState] = useState({store});
  useEffect(() => {
    const onChange = () => {
      setStoreState({store});
    }
    store.on('change', onChange);
    return () => {
      store.off('change', onChange);
    }
  }, []);
  return storeState.store;
}

withStores HOC handle store updates

export default function (...stores: SimpleStore[]) {
  return function (WrappedComponent: React.ComponentType<any>) {
    return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
      constructor(props: React.ComponentProps<any>) {
        super(props);
        this.state = {
          lastUpdated: Date.now(),
        };
        this.stores = stores;
      }

      private stores?: SimpleStore[];

      private onChange = () => {
        this.setState({lastUpdated: Date.now()});
      };

      componentDidMount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            // each store has a common change event to subscribe to
            store.on('change', this.onChange);
          });
      };

      componentWillUnmount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            store.off('change', this.onChange);
          });
      };

      render() {
        return (
          <WrappedComponent
            lastUpdated={this.state.lastUpdated}
            {...this.props}
          />
        );
      }
    };
  };
}

SimpleStore class

import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';

interface SimpleStoreArgs {
  key?: string;
  defaultState?: {[key: string]: any};
}

export default class SimpleStore {
  constructor({key, defaultState}: SimpleStoreArgs) {
    if (key) {
      this.key = key;
      // hydrate here if you want w/ localState or AsyncStorage
    }
    if (defaultState) {
      this._state = {...defaultState, loaded: false};
    } else {
      this._state = {loaded: true};
    }
  }
  protected key: string = '';
  protected _state: {[key: string]: any} = {};
  protected eventEmitter: Emitter = ee({});
  public setState(newState: {[key: string]: any}) {
    this._state = {...this._state, ...newState};
    this.eventEmitter.emit('change');
    if (this.key) {
      // store on client w/ localState or AsyncStorage
    }
  }
  public get state() {
    return this._state;
  }
  public on(ev: string, fn:() => void) {
    this.eventEmitter.on(ev, fn);
  }
  public off(ev: string, fn:() => void) {
    this.eventEmitter.off(ev, fn);
  }
  public get loaded(): boolean {
    return !!this._state.loaded;
  }
}

How to Use

In the case of hooks:

// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';

In the case of HOC:

// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);

MAKE SURE To export your stores as a singleton to get the benefit of global change like so:

class MyStore extends SimpleStore {
  public get someProp() {
    return this._state.someProp || '';
  }
  public set someProp(value: string) {
    this.setState({...this._state, someProp: value});
  }
}
// this is a singleton
const myStore = new MyStore();
export {myStore};

This approach is pretty simple and works for me. I also work in large teams and use Redux and MobX and find those to be good as well but just a lot of boilerplate. I just personally like my own approach because I always hated a lot of code for something that can be simple when you need it to be.

Indefectible answered 23/11, 2017 at 18:36 Comment(3)
I think there is a typo in your Store class example in the update method having to write the first line of the method as following: this._data = {...this._data, ...newData}.Acetous
React discourages inheritance in favor of composition. reactjs.org/docs/composition-vs-inheritance.htmlSedimentary
Just wondering about clarity/readibility, how coud this.setState(this.state) be better than this.forceUpdate()?Ir
W
22

So I guess my question is: do React components need to have state in order to rerender? Is there a way to force the component to update on demand without changing the state?

The other answers have tried to illustrate how you could, but the point is that you shouldn't. Even the hacky solution of changing the key misses the point. The power of React is giving up control of manually managing when something should render, and instead just concerning yourself with how something should map on inputs. Then supply stream of inputs.

If you need to manually force re-render, you're almost certainly not doing something right.

Wipe answered 8/9, 2016 at 16:42 Comment(0)
X
13

For completeness, you can also achieve this in functional components:

const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();

Or, as a reusable hook:

const useForceUpdate = () => {
  const [, updateState] = useState();
  return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();

See: https://mcmap.net/q/54123/-how-can-i-force-a-component-to-re-render-with-hooks-in-react

Please note that using a force-update mechanism is still bad practice as it goes against the react mentality, so it should still be avoided if possible.

Ximenes answered 22/10, 2019 at 21:32 Comment(0)
P
9

There are a few ways to rerender your component:

The simplest solution is to use forceUpdate() method:

this.forceUpdate()

One more solution is to create not used key in the state(nonUsedKey) and call setState function with update of this nonUsedKey:

this.setState({ nonUsedKey: Date.now() } );

Or rewrite all current state:

this.setState(this.state);

Props changing also provides component rerender.

Postpaid answered 19/3, 2019 at 13:55 Comment(0)
I
6

You could do it a couple of ways:

1. Use the forceUpdate() method:

There are some glitches that may happen when using the forceUpdate() method. One example is that it ignores the shouldComponentUpdate() method and will re-render the view regardless of whether shouldComponentUpdate() returns false. Because of this using forceUpdate() should be avoided when at all possible.

2. Passing this.state to the setState() method

The following line of code overcomes the problem with the previous example:

this.setState(this.state);

Really all this is doing is overwriting the current state with the current state which triggers a re-rendering. This still isn't necessarily the best way to do things, but it does overcome some of the glitches you might encounter using the forceUpdate() method.

Ibby answered 1/9, 2017 at 23:41 Comment(3)
Since setState is batched it's probably safer to do: this.setState(prevState => prevState);Inherence
Not really sure why that is a 'glitch'. The name of the method ('forceUpdate') could not be clearer: force the update always.Ir
@Zoman, definition of glitch from dictionary: "a small problem or mistake that prevents something from being successful or working as well as it should". forceUpdate is not the glitch itself, but can cause glitches and give you unexpected results that need to be overcome via other methods.Ibby
B
5

We can use this.forceUpdate() as below.

       class MyComponent extends React.Component {



      handleButtonClick = ()=>{
          this.forceUpdate();
     }


 render() {

   return (
     <div>
      {Math.random()}
        <button  onClick={this.handleButtonClick}>
        Click me
        </button>
     </div>
    )
  }
}

 ReactDOM.render(<MyComponent /> , mountNode);

The Element 'Math.random' part in the DOM only gets updated even if you use the setState to re-render the component.

All the answers here are correct supplementing the question for understanding..as we know to re-render a component with out using setState({}) is by using the forceUpdate().

The above code runs with setState as below.

 class MyComponent extends React.Component {



             handleButtonClick = ()=>{
                this.setState({ });
              }


        render() {
         return (
  <div>
    {Math.random()}
    <button  onClick={this.handleButtonClick}>
      Click me
    </button>
  </div>
)
  }
 }

ReactDOM.render(<MyComponent /> , mountNode);
Bellboy answered 6/7, 2018 at 13:10 Comment(0)
C
2

Just another reply to back-up the accepted answer :-)

React discourages the use of forceUpdate() because they generally have a very "this is the only way of doing it" approach toward functional programming. This is fine in many cases, but many React developers come with an OO-background, and with that approach, it's perfectly OK to listen to an observable object.

And if you do, you probably know you MUST re-render when the observable "fires", and as so, you SHOULD use forceUpdate() and it's actually a plus that shouldComponentUpdate() is NOT involved here.

Tools like MobX, that takes an OO-approach, is actually doing this underneath the surface (actually MobX calls render() directly)

Croissant answered 1/11, 2018 at 9:44 Comment(0)
D
2

forceUpdate(), but every time I've ever heard someone talk about it, it's been followed up with you should never use this.

Dani answered 8/7, 2019 at 0:51 Comment(0)
J
1

I have found it best to avoid forceUpdate(). One way to force re-render is to add dependency of render() on a temporary external variable and change the value of that variable as and when needed.

Here's a code example:

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

Call this.forceChange() when you need to force re-render.

Justly answered 26/12, 2017 at 6:12 Comment(0)
L
1

Another way is calling setState, AND preserve state:

this.setState(prevState=>({...prevState}));

Lazaretto answered 24/7, 2018 at 11:54 Comment(0)
A
1

forceUpdate(); method will work but it is advisable to use setState();

Aforetime answered 21/8, 2018 at 15:7 Comment(0)
V
1

In order to accomplish what you are describing please try this.forceUpdate().

Vermiculite answered 18/9, 2018 at 14:17 Comment(1)
What does this action do?Cytogenesis
S
0

Yes , if u render components in array , u can use array filter with a unique identifier in each component in order to get a specific component and rerender the component array

Spinozism answered 30/6, 2023 at 19:10 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Globetrotter
G
0

With the use of the forceUpdate method, you can force a component to update without changing its state. For example:

export default class MyComponent extends React.Component {
  handleButtonClick = () => {
    this.forceUpdate(); // Force a re-render
  }
}
Glyndaglynias answered 7/11, 2023 at 16:26 Comment(0)
T
-1

ES6 - I am including an example, which was helpful for me:

In a "short if statement" you can pass empty function like this:

isReady ? ()=>{} : onClick

This seems to be the shortest approach.

()=>{}
Taitaichung answered 30/5, 2018 at 18:52 Comment(1)
Absolut off-topic.Sporule
B
-1

use 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 changed, 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:

 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.

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>
  );
}
Blubber answered 20/11, 2021 at 6:27 Comment(0)
M
-6

You can use forceUpdate() for more details check (forceUpdate()).

Maul answered 2/7, 2019 at 18:16 Comment(1)
Out of curiosity, why leave this answer if for 4 years people have already offered that as a possible solution in this thread?Ugly

© 2022 - 2024 — McMap. All rights reserved.