componentWillReceiveProps, componentDidUpdate für React Hook

Lesezeit: 7 Minuten

Benutzeravatar von Deng Zhebin
Deng Zhebin

Ich stoße auf zwei Herausforderungen:

  • Auch wenn, laut React-Richtlinie, abgeleiteter Zustand wird davon abgeraten, aber einige Grenzfälle brauchen es immer noch.
    In Bezug auf eine funktionale Komponente mit React Hook, Was ist die äquivalente Implementierung mit React Hook, wenn ich einen abgeleiteten Zustand benötige, der in der Klassenkomponente bei jedem übergeordneten Rendering in componentWillReceiveProps aktualisiert wird

siehe unten Codebeispiel:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: props.count > 100 ? 100 : props.count,
    }

  }

  /*What is the equivalent implementation when React Hook is used here componentWillReceiveProps*/
  componentWillReceiveProps(nextProps) {
    if (nextProps.count !== this.props.count) {
      this.setState({
        count: nextProps.count > 100 ? 100 : nextProps.count
      });
    }
  }

  render() {
    return ( <
      div > {
        this.state.count
      } <
      /div>
    );
  }
}

export default App;
  • Wie für componentDidUpdate hat componentDidUpdate sein Gegenstück, wenn React Hook verwendet wird, Sie müssen es wie folgt verwenden:

      React.useEffect(() => {
        return () => {
    
         };
      }, [parentProp]);
    

    Der zweite Parameter für useEffect stellt sicher, dass Code nur ausgeführt wird, wenn sich Prop ändert, aber Was ist, wenn ich entsprechende Aufgaben basierend auf mehreren entsprechenden Requisitenänderungen ausführen möchte?? wie man es hinbekommt mit useEffect?

siehe unten Codebeispiel:

class App extends Component {


  /*What is the equivalent implementation when functional component with React Hook is used here */
  componentDidUpdate(prevProps, prevState) {
    if (prevProps.groupName !== this.props.groupName) {
      console.log('Let'
        's say, I do want to do some task here only when groupName differs');
    } else if (prevProps.companyName !== this.props.companyName) {
      console.log('Let'
        's say, I do want to do some different task here only when companyName differs');
    }

  }


  render() {
    /*for simplicity, render code is ignored*/
    return null;
  }
}

export default App;

Benutzeravatar von fgonzalez
fgonzalez

Der Reaktionshaken entspricht dem alten componentWillReceive Requisiten können mit dem gemacht werden useEffect Hook, indem Sie einfach die Prop angeben, die wir auf Änderungen im Abhängigkeitsarray überwachen möchten.

Dh:

export default (props) => {

    useEffect( () => {
        console.log('counter updated');
    }, [props.counter])

    return <div>Hi {props.counter}</div>
}

Zum componentDidUpdate nur durch Weglassen des Abhängigkeitsarrays, the useEffect Funktion wird nach jedem erneuten Rendern aufgerufen.

Dh:

export default (props) => {

    useEffect( () => {
        console.log('counter updated');
    })

    return <div>Hi {props.counter}</div>
}

  • Nachdem ich einige umfangreiche Recherchen zu diesem Thema durchgeführt habe, würde ich argumentieren, dass Ihre Erklärung von componentWillReceiveProps falsch ist. Das Problem ist also, dass das Ersetzen von „componentWillReceiveProps“ schwierig ist, da es sich um eine Pre-Render-Funktion handelt. Dies ist bei Reaktionshaken nicht der Fall. Sie können useRef() verwenden, um die vorherige Stütze zu speichern und sie mit der aktuellen in der useEffect-Funktion zu vergleichen, um zu versuchen, die Funktionalität zu replizieren, aber selbst das ist möglicherweise nicht genau ein 1:1-Ersatz.

    – Zach Pedigo

    20. Oktober 2020 um 15:09 Uhr

Du kannst den … benutzen useMemo Haken, um eine Berechnung zu speichern und zu setzen props.count in dem als zweites Argument angegebenen Array, um den Wert neu zu berechnen, wenn er sich ändert.

const { useState, useEffect, useMemo } = React;

function App() {
  const [count, setCount] = useState(50);

  useEffect(() => {
    setTimeout(() => {
      setCount(150);
    }, 2000);
  }, []);

  return <DisplayCount count={count} />;
}

function DisplayCount(props) {
  const count = useMemo(() => props.count > 100 ? 100 : props.count, [props.count]);

  return <div> {count} </div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Der einfachste Weg, separate Effekte zu erzielen, wenn sich separate Requisiten ändern, besteht darin, mehrere zu erstellen useEffect Hooks, die nur ausgeführt werden, wenn sich eine der separaten Requisiten ändert.

const { useState, useEffect } = React;

function App() {
  const [groupName, setGroupName] = useState('foo');
  const [companyName, setCompanyName] = useState('foo');

  useEffect(() => {
    setTimeout(() => {
      setGroupName('bar');
    }, 1000);
    setTimeout(() => {
      setCompanyName('bar');
    }, 2000);
  }, []);

  return <DisplayGroupCompany groupName={groupName} companyName={companyName} />;
}

function DisplayGroupCompany(props) {
  useEffect(() => {
    console.log("Let's say, I do want to do some task here only when groupName differs");
  }, [props.groupName])
  useEffect(() => {
    console.log("Let's say,I do want to do some different task here only when companyName differs");
  }, [props.companyName])

  return <div> {props.groupName} - {props.companyName} </div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Wenn Sie den useMemo-Hook oben auf Ihrer Komponente verwenden und ihn von all Ihren Requisiten abhängig machen, wird er jedes Mal vor allem ausgeführt, wenn sich Requisiten ändern. useEffect wird nach dem aktualisierten Rendern ausgelöst und da es von allen Requisiten abhängig ist, wird es nach einem erneuten Rendern von allen Requisiten ausgelöst.

const Component = (...props) => {
   // useState, useReducer if have
   useMemo(() => {
     // componentWillReceiveProps
   },[...props]);
   // ...other logic and stuff
   useEffect(() => {
     // componentDidUpdate
   }, [...props]);
};

  • Ich bin froh, das zu wissen, es ist wirklich hilfreich, den Unterschied zwischen diesen zu erkennen. Vielen Dank ..!

    – Sanat Gupta

    15. Oktober 2020 um 17:45 Uhr

Benutzeravatar von Thien Ly
Thien Ly

setCount löst ein erneutes Rendern aus. Verwenden useEffect mit [count] da das Abhängigkeitsarray sicherstellt, dass der Hook nur Aufrufe durchführt setCount Wenn countDer Wert von ändert sich.

So gehen Sie vor, um alles zu ersetzen componentWillReceiveProps Logik, die Sie sonst vielleicht im alten klassenbasierten React-Stil geschrieben hätten. Ich finde das “Jeder Renderer hat seine eigenen Requisiten und seinen eigenen Status“Prinzip nützlich: Wenn Sie nur dann ein erneutes Rendern auslösen möchten, wenn sich bestimmte Requisiten ändern, können Sie mehrere haben useEffect Haken.

useEffect(() => {
  count > 100 ? setCount(100) : setCount(count)
}, [count]) 
 
useEffect(() => {
  console.log('groupName has changed');
  // do something with groupName
}, [groupName])
    
useEffect(() => {
  console.log('companyName has changed');
  // do something with companyName
}, [companyName]) 

Benutzeravatar von Kevin F
Kevin F.

In Ihrem Szenario müssen Sie nicht verwenden oder neu implementieren getDerivedStateFromProps überhaupt. Sie müssen nur eine neue Variable erstellen, um die neue Form von Daten zu erhalten. Die Verwendung von state in diesem Szenario führt nur zu einem erneuten Rendern, was in Bezug auf die Leistung nicht gut ist.

import React from 'react';

const App = ({ count }) => {
  const derivedCount = count > 100 ? 100 : count;

  return (
    <div>Counter: {derivedCount}</div>
  );
}

App.propTypes = {
  count: PropTypes.number.isRequired
}

Demo hier: https://codesandbox.io/embed/qzn8y9y24j?fontsize=14

Sie können mehr über verschiedene Möglichkeiten lesen, um diese Art von Szenarien zu lösen, ohne zu verwenden getDerivedStateFromProps hier: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

Wenn Sie wirklich einen separaten Status verwenden müssen, können Sie so etwas verwenden

import React, { useState } from 'react';

const App = ({ count }) => {
  const [derivedCounter, setDerivedCounter] = useState(
    count > 100 ? 100 : count
  );

  useEffect(() => {
    setDerivedCounter(count > 100 ? 100 : count);
  }, [count]); // this line will tell react only trigger if count was changed

  return <div>Counter: {derivedCounter}</div>;
};

  • ist es nicht wahr, dass prop schreibgeschützt ist? und das Wechseln der Stütze bricht auch die reine Funktion. Rechts?

    – MPV

    4. August 2019 um 7:06 Uhr

Benutzeravatar von kwoxer
kwoxer

einfach durch Verwendung von useEffect wie folgt.

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.

  • ist es nicht wahr, dass prop schreibgeschützt ist? und das Wechseln der Stütze bricht auch die reine Funktion. Rechts?

    – MPV

    4. August 2019 um 7:06 Uhr

In einem Fall möchten Sie ein Protokollsystem wie z warum hast du gerendertund Sie brauchen die nextProps Hier hilft Haken.

  • An der alten Lebenszyklusfunktion ausgerichtet, um Sachen in Props und nextProps umzubenennen
  • nextProps bedeutet aktuelle Requisiten
  • Requisiten bedeuten frühere Requisiten
const useComponentWillReceiveProps(nextProps, callback) {
  const props = useRef(nextProps) 

  useEffect(() => {
    callback(nextProps, props.current)
    props.current = nextProps
  })
}

Verwendungszweck

const diffLogger = (nextProps, props, { name = "Component" } = {}) => {
  Object.keys(nextProps)
    .filter((key) => nextProps[key] !== props[key])
    .forEach((key) => {
      console.log(
        `%c${name}:%c${key}`,
        "color:#ff5722; font-size:1rem; font-weight:bold;",
        "color:#ffc107; font-size:1.2rem; font-weight:bold;",
        {
          from: props[key],
          to: nextProps[key],
        }
      )
    })
}
const Button = (props) => {
 useComponentWillReceiveProps(props, diffLogger, {name: 'Button'})
 return <button onClick={props.onClick}>Button</button>
}

Jetzt Wenn Sie Ihre Schaltfläche neu rendern zB durch onClick neue Referenz erhalten Sie so etwas:
Geben Sie hier die Bildbeschreibung ein

1403370cookie-checkcomponentWillReceiveProps, componentDidUpdate für React Hook

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy