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

前端 未结 16 2210
误落风尘
误落风尘 2020-11-29 00:28

Considering below hooks example

   import { useState } from \'react\';

   function Example() {
       const [count, setCount] = useState(0);

       return         


        
相关标签:
16条回答
  • 2020-11-29 01:17

    For regular React Class based components, refer to React Docs for the forceUpdate api at this URL. The docs mention that:

    Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render()

    However, it is also mentioned in the docs that:

    If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().

    So, although use cases for using forceUpdate might be rare, and I have not used it ever, however I have seen it used by other developers in some legacy corporate projects that I have worked on.

    So, for the equivalent functionality for Functional Components, refer to the React Docs for HOOKS at this URL. Per the above URL, one can use the "useReducer" hook to provide a forceUpdate functionality for Functional Components.

    A working code sample that does not use state or props is provided below, which is also available on CodeSandbox at this URL

    import React, { useReducer, useRef } from "react";
    import ReactDOM from "react-dom";
    
    import "./styles.css";
    
    function App() {
      // Use the useRef hook to store a mutable value inside a functional component for the counter
      let countref = useRef(0);
    
      const [, forceUpdate] = useReducer(x => x + 1, 0);
    
      function handleClick() {
        countref.current++;
        console.log("Count = ", countref.current);
        forceUpdate(); // If you comment this out, the date and count in the screen will not be updated
      }
    
      return (
        <div className="App">
          <h1> {new Date().toLocaleString()} </h1>
          <h2>You clicked {countref.current} times</h2>
          <button
            onClick={() => {
              handleClick();
            }}
          >
            ClickToUpdateDateAndCount
          </button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    NOTE: An alternate approach using the useState hook (instead of useReducer) is also available at this URL.

    0 讨论(0)
  • 2020-11-29 01:18

    You should preferably only have your component depend on state and props and it will work as expected, but if you really need a function to force the component to re-render, you could use the useState hook and call the function when needed.

    Example

    const { useState, useEffect } = React;
    
    function Foo() {
      const [, forceUpdate] = useState();
    
      useEffect(() => {
        setTimeout(forceUpdate, 2000);
      }, []);
    
      return <div>{Date.now()}</div>;
    }
    
    ReactDOM.render(<Foo />, document.getElementById("root"));
    <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    0 讨论(0)
  • 2020-11-29 01:18

    react-tidy has a custom hook just for doing that called useRefresh:

    import React from 'react'
    import {useRefresh} from 'react-tidy'
    
    function App() {
      const refresh = useRefresh()
      return (
        <p>
          The time is {new Date()} <button onClick={refresh}>Refresh</button>
        </p>
      )
    }
    

    Learn more about this hook

    Disclaimer I am the writer of this library.

    0 讨论(0)
  • 2020-11-29 01:19

    As the others have mentioned, useState works - here is how mobx-react-lite implements updates - you could do something similar.

    Define a new hook, useForceUpdate -

    import { useState, useCallback } from 'react'
    
    export function useForceUpdate() {
      const [, setTick] = useState(0);
      const update = useCallback(() => {
        setTick(tick => tick + 1);
      }, [])
      return update;
    }
    

    and use it in a component -

    const forceUpdate = useForceUpdate();
    if (...) {
      forceUpdate(); // force re-render
    }
    

    See https://github.com/mobxjs/mobx-react-lite/blob/master/src/utils.ts and https://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver.ts

    0 讨论(0)
提交回复
热议问题