Ich versuche, den Status mithilfe von React hook setState () mithilfe der Requisiten festzulegen, die die Komponente erhält. Ich habe versucht, den folgenden Code zu verwenden:
import React,{useState , useEffect} from 'react';
const Persons = (props) => {
// console.log(props.name);
const [nameState , setNameState] = useState(props)
console.log(nameState.name);
console.log(props.name);
return (
<div>
<p>My name is {props.name} and my age is {props.age}</p>
<p>My profession is {props.profession}</p>
</div>
)
}
export default Persons;
Das Problem ist, dass der Status beim Laden der Komponente festgelegt wird. Aber wenn es neue Requisiten erhält, wird der Zustand nicht aktualisiert. Wie aktualisiere ich den Status in diesem Fall? Danke im Voraus.
reactjs
react-hooks
METALLKOPF
quelle
quelle
setNameState
.useEffect
Antworten:
useState
Das Hooks-Funktionsargument wird nur einmal verwendet und nicht jedes Mal, wenn sich die Requisite ändert. Sie müssenuseEffect
Hooks verwenden, um das zu implementieren, was Sie alscomponentWillReceiveProps/getDerivedStateFromProps
Funktionalität bezeichnen würdenimport React,{useState , useEffect} from 'react'; const Persons = (props) => { const [nameState , setNameState] = useState(props) useEffect(() => { setNameState(props); }, [props]) return ( <div> <p>My name is {props.name} and my age is {props.age}</p> <p>My profession is {props.profession}</p> </div> ) } export default Persons;
quelle
props.name
undprops.age
etc. in der Rücksendung anstelle vonnameState.name
&nameState.age
etc.?Diese allgemeine Idee kann in den Haken gelegt werden:
export function useStateFromProp(initialValue) { const [value, setValue] = useState(initialValue); useEffect(() => setValue(initialValue), [initialValue]); return [value, setValue]; } function MyComponent({ value: initialValue }) { const [value, setValue] = useStateFromProp(initialValue); return (...); }
quelle
Der
props
Wert inuseState(props)
wird nur während des ersten Renderns verwendet , weitere Statusaktualisierungen werden mit dem Setter durchgeführtsetNameState
.Darüber hinaus ist
useEffect
beim Aktualisieren des abgeleiteten Status Folgendes nicht erforderlich :const Person = props => { const [nameState, setNameState] = useState(props.name); // update derived state conditionally without useEffect if (props.name !== nameState) setNameState(props.name); // ... other render code };
Aus React-Dokumenten :
Im Wesentlichen können wir die Leistung optimieren, indem wir eine zusätzliche Browser-Repaint-Phase wie z
useEffect
immer ausgeführt wird, nachdem das Rendern auf dem Bildschirm festgeschrieben wurde.Arbeitsbeispiel
Dies ist ein erfundenes Beispiel, das das obige Muster veranschaulicht - in echtem Code würden Sie
props.name
direkt lesen . Weitere geeignete Anwendungsfälle für abgeleitete Zustände finden Sie im React-Blogbeitrag .Code-Snippet anzeigen
const Person = props => { const [nameState, setNameState] = React.useState(props.name); // Here, we update derived state without useEffect if (props.name !== nameState) setNameState(props.name); return ( <p> <h3>Person</h3> <div>{nameState} (from derived state)</div> <div>{props.name} (from props)</div> <p>Note: Derived state is synchronized/contains same value as props.name</p> </p> ); }; const App = () => { const [personName, setPersonName] = React.useState("Lui"); const changeName = () => setPersonName(personName === "Lukas" ? "Lui" : "Lukas"); return ( <div> <Person name={personName} /> <button onClick={changeName}>Change props</button> </div> ); }; ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script> <div id="root"></div>
quelle
if (props.name.first !== nameState.first)
. Oder verwenden Sie einen tiefen VergleichshelferDafür müssen Sie das verwenden,
useEffect
damit Ihr Code aussieht. Da Sie vermeiden möchten, erneut zu rendern, wenn sich die Profis nicht geändert haben, müssen Sie zuerst useEffect überprüfen und dann die Requisiten auf die aktuelle Variable setzen.import React, { useState, useEffect } from "react"; const Persons = props => { // console.log(props.name); const [nameState, setNameState] = useState(props); console.log(nameState.name); console.log(props.name); useEffect( () => { if (nameState !== props.name) { setNameState(props.name); } }, [nameState] ); return ( <div> <p> My name is {props.name} and my age is {props.age} </p> <p>My profession is {props.profession}</p> </div> ); }; export default Persons;
Demo
quelle
setNameState()
löst ein anderes aus. Scheint mir zweimal.import React, { useState, useEffect } from "react"; const Persons = props => { // console.log(props.name); const [nameState, setNameState] = useState(props); console.log(nameState.name); console.log(props.name); useEffect( () => { if (nameState !== props) { setNameState(props); } }, [nameState] ); return ( <div> <p> My name is {props.name} and my age is {props.age} </p> <p>My profession is {props.profession}</p> </div> ); }; export default Persons;
Gemäß dem Hooks-Reaktionsdokument wird useEffect immer dann aufgerufen, wenn Requisiten oder Komponenten aktualisiert werden. Sie müssen also die Bedingung überprüfen, bevor Sie useState aktualisieren, und dann Ihren Wert aktualisieren, damit er nicht ständig neu gerendert wird
quelle
Ich glaube, das Problem deutet auf einen Versuch hin, eine konzeptionelle Variable oder einen Satz von Variablen zu verwenden, um zwei verschiedene Dinge zu tun. Zum Beispiel versuchen, dasselbe zu bekommen
props.name
undname
zu tun.Also wenn
const [name, setName] = useState(props.name)
ist nicht genug und Sie versuchen, später in der Funktion in die
props.name
Statusvariable zu zwingen,name
dannname
wird sie möglicherweise überlastet. Versuchen Sie, eine andere Zustandsvariable einzurichten - z.updatedName
und sehen, ob die Dinge besser funktionieren.Das ursprüngliche Beispiel zeigt dieses Problem nicht, da die Statusvariablen nur in Protokollanweisungen verwendet werden.
Wenn es
const [name, setName] = useState(props.name)
bei einem erneuten Rendern aktualisiert wird, macht es keinen Sinn, eine Statusvariable zu haben,name
da diese immer dieselbe ist wieprops.name
(und weitere Versuche, sie zu ändern, würden ein erneutes Rendern verursachen).quelle