componentWillReceiveProps, componentDidUpdate for React Hook

后端 未结 8 1140
闹比i
闹比i 2020-12-25 11:00

I run into two challenges:

  • Even if, as per React guideline, derived state is discouraged, but some edge cases still need it.
    In terms of
相关标签:
8条回答
  • 2020-12-25 11:33

    simply by using useEffect like this.

    useEffect( () => {
        props.actions.fetchSinglePost(props.match.params.id); //> I'm dispatching an action here.
    }, [props.comments]) //> and here to watch comments and call the action in case there is any change.
    
    0 讨论(0)
  • 2020-12-25 11:36

    I realize your "derived state" example is intentionally simple, but because there are so few legitimate cases of derived state, it is difficult to make a recommendation on the replacement except on a case-by-case basis since it depends on the reason you are using derived state. In the particular example you provided, there was no reason to use derived state in the class case and so there continues to be no reason in the hook case (the value can just be derived locally without putting it in state). If the derived value is expensive, you can use useMemo as Tholle presents. If these don't fit the more realistic case(s) you have in mind, you would need to present a more specific case that truly requires derived state.

    As far as your componentDidUpdate example, if what you want to do for the different props is independent, then you can use separate effects for each (i.e. multiple useEffect calls). If you want to do exactly what is in your example (i.e. only do something for a companyName change if groupName didn't also change as indicated by your else if), then you can use refs for more sophisticated conditions. You should not mutate the ref during rendering (there is always the possibility of the render being discarded/redone once concurrent mode is supported), so the example uses the last effect to make updates to the refs. In my example, I use a ref to avoid doing effect work on the initial render (see Tholle's answer in this related question) and to detect whether or not groupName changed when deciding whether or not to do work based on a companyName change.

    const { useState, useEffect, useRef } = React;
    
    const DerivedStateFromProps = ({ count }) => {
      const derivedCount = count > 100 ? 100 : count;
    
      return (
        <div>
          Derived from {count}: {derivedCount}{" "}
        </div>
      );
    };
    const ComponentDidUpdate = ({ groupName, companyName }) => {
      const initialRender = useRef(true);
      const lastGroupName = useRef(groupName);
      useEffect(
        () => {
          if (!initialRender.current) {
            console.log("Do something when groupName changes", groupName);
          }
        },
        [groupName]
      );
      useEffect(
        () => {
          if (!initialRender.current) {
            console.log("Do something when companyName changes", companyName);
          }
        },
        [companyName]
      );
      useEffect(
        () => {
          if (!initialRender.current && groupName === lastGroupName.current)
            console.log(
              "Do something when companyName changes only if groupName didn't also change",
              companyName
            );
        },
        [companyName]
      );
      useEffect(
        () => {
          // This effect is last so that these refs can be read accurately in all the other effects.
          initialRender.current = false;
          lastGroupName.current = groupName;
        },
        [groupName]
      );
    
      return null;
    };
    function App() {
      const [count, setCount] = useState(98);
      const [groupName, setGroupName] = useState("initial groupName");
      const [companyName, setCompanyName] = useState("initial companyName");
      return (
        <div>
          <div>
            <DerivedStateFromProps count={count} />
            <button onClick={() => setCount(prevCount => prevCount + 1)}>
              Increment Count
            </button>
          </div>
          <div>
            <ComponentDidUpdate groupName={groupName} companyName={companyName} />
            groupName:{" "}
            <input
              type="text"
              value={groupName}
              onChange={event => setGroupName(event.target.value)}
            />
            <br />
            companyName:{" "}
            <input
              type="text"
              value={companyName}
              onChange={event => setCompanyName(event.target.value)}
            />
            <br />
            change both{" "}
            <input
              type="text"
              onChange={event => {
                const suffix = event.target.value;
                setGroupName(prev => prev + suffix);
                setCompanyName(prev => prev + suffix);
              }}
            />
          </div>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    <div id="root"></div>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

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