Was ist die richtige Methode zum Aktualisieren des Status, ist ein verschachteltes Objekt in Reagieren mit Hooks?
export Example = () => {
const [exampleState, setExampleState] = useState(
{masterField: {
fieldOne: "a",
fieldTwo: {
fieldTwoOne: "b"
fieldTwoTwo: "c"
}
}
})
Wie würde man verwenden , setExampleState
um Updates exampleState
zu a
(ein Feld anhängen)?
const a = {
masterField: {
fieldOne: "a",
fieldTwo: {
fieldTwoOne: "b",
fieldTwoTwo: "c"
}
},
masterField2: {
fieldOne: "c",
fieldTwo: {
fieldTwoOne: "d",
fieldTwoTwo: "e"
}
},
}
}
b
(Werte ändern)?
const b = {masterField: {
fieldOne: "e",
fieldTwo: {
fieldTwoOne: "f"
fieldTwoTwo: "g"
}
}
})
javascript
reactjs
react-hooks
isaacsultan
quelle
quelle
Antworten:
Sie können einen neuen Wert wie diesen übergeben
setExampleState({...exampleState, masterField2: { fieldOne: "c", fieldTwo: { fieldTwoOne: "d", fieldTwoTwo: "e" } }, }})
quelle
masterField
stattmasterField2
setExampleState({...exampleState, masterField:
{// neue Werte}setExampleState( exampleState => ({...exampleState, masterField2: {...etc} }) );
Wenn jemand nach useState () sucht, aktualisiert Hooks das Objekt
- Through Input const [state, setState] = useState({ fName: "", lName: "" }); const handleChange = e => { const { name, value } = e.target; setState(prevState => ({ ...prevState, [name]: value })); }; <input value={state.fName} type="text" onChange={handleChange} name="fName" /> <input value={state.lName} type="text" onChange={handleChange} name="lName" /> *************************** - Through onSubmit or button click setState(prevState => ({ ...prevState, fName: 'your updated value here' }));
quelle
Im Allgemeinen sollten Sie auf tief verschachtelte Objekte im Status "Reagieren" achten. Um unerwartetes Verhalten zu vermeiden, sollte der Status unveränderlich aktualisiert werden. Wenn Sie tiefe Objekte haben, klonen Sie diese tief, um Unveränderlichkeit zu erreichen, was in React sehr teuer sein kann. Warum?
Sobald Sie den Status tief geklont haben, berechnet React alles neu und rendert es neu, was von den Variablen abhängt, auch wenn sie sich nicht geändert haben!
Überlegen Sie sich also zunächst, wie Sie den Status reduzieren können, bevor Sie versuchen, Ihr Problem zu lösen. Sobald Sie dies tun, finden Sie schöne Tools, die Ihnen beim Umgang mit großen Zuständen helfen, wie z. B. useReducer ().
Für den Fall , haben Sie darüber nach , sind aber nach wie vor davon überzeugt , benötigen Sie einen tief verschachtelten Zustand Baum zu verwenden, haben Sie immer useState () mit Bibliotheken wie können immutable.js und Unveränderlichkeit-Helfer . Sie machen es einfach, tiefe Objekte zu aktualisieren oder zu klonen, ohne sich um die Veränderlichkeit sorgen zu müssen.
quelle
Danke Philip, das hat mir geholfen. Mein Anwendungsfall war, dass ich ein Formular mit vielen Eingabefeldern hatte, sodass ich den Anfangszustand als Objekt beibehalten und den Objektstatus nicht aktualisieren konnte. Der obige Beitrag hat mir geholfen :)
const [projectGroupDetails, setProjectGroupDetails] = useState({ "projectGroupId": "", "projectGroup": "DDD", "project-id": "", "appd-ui": "", "appd-node": "" }); const inputGroupChangeHandler = (event) => { setProjectGroupDetails((prevState) => ({ ...prevState, [event.target.id]: event.target.value })); } <Input id="projectGroupId" labelText="Project Group Id" value={projectGroupDetails.projectGroupId} onChange={inputGroupChangeHandler} />
quelle
Ich bin zu spät zur Party .. :)
Die Antwort von @aseferov funktioniert sehr gut, wenn die gesamte Objektstruktur erneut eingegeben werden soll. Wenn das Ziel jedoch darin besteht, einen bestimmten Feldwert in einem Objekt zu aktualisieren, ist der folgende Ansatz meiner Meinung nach besser.
Lage:
const [infoData, setInfoData] = useState({ major: { name: "John Doe", age: "24", sex: "M", }, minor:{ id: 4, collegeRegion: "south", } });
Für die Aktualisierung eines bestimmten Datensatzes muss der vorherige Status wiederhergestellt werden
prevState
Hier:
setInfoData((prevState) => ({ ...prevState, major: { ...prevState.major, name: "Tan Long", } }));
vielleicht
setInfoData((prevState) => ({ ...prevState, major: { ...prevState.major, name: "Tan Long", }, minor: { ...prevState.minor, collegeRegion: "northEast" }));
Ich hoffe, dies hilft jedem, der versucht, ein ähnliches Problem zu lösen.
quelle
()
Um dies einfach zu beantworten;setInfoData
Dies liegt daran, dass es von Natur aus von hoher Ordnung ist, dh es kann dank der vom Hook bereitgestellten Leistung eine andere Funktion als Argument übernehmen: useState. Ich hoffe, dieser Artikel bietet mehr Klarheit über Funktionen höherer Ordnung: sitepoint.com/higher-order-functions-javascriptfunction App() { const [todos, setTodos] = useState([ { id: 1, title: "Selectus aut autem", completed: false }, { id: 2, title: "Luis ut nam facilis et officia qui", completed: false }, { id: 3, title: "Fugiat veniam minus", completed: false }, { id: 4, title: "Aet porro tempora", completed: true }, { id: 5, title: "Laboriosam mollitia et enim quasi", completed: false } ]); const changeInput = (e) => {todos.map(items => items.id === parseInt(e.target.value) && (items.completed = e.target.checked)); setTodos([...todos], todos);} return ( <div className="container"> {todos.map(items => { return ( <div key={items.id}> <label> <input type="checkbox" onChange={changeInput} value={items.id} checked={items.completed} /> {items.title}</label> </div> ) })} </div> ); }
quelle
Ich denke, die beste Lösung ist Immer . Sie können das Objekt so aktualisieren, als würden Sie Felder direkt ändern (masterField.fieldOne.fieldx = 'abc'). Aber das eigentliche Objekt wird sich natürlich nicht ändern. Es sammelt alle Aktualisierungen eines Entwurfsobjekts und gibt Ihnen am Ende ein endgültiges Objekt, mit dem Sie das ursprüngliche Objekt ersetzen können.
quelle
Ich überlasse Ihnen eine Utility-Funktion, um Objekte unveränderlich zu aktualisieren
/** * Inmutable update object * @param {Object} oldObject Object to update * @param {Object} updatedValues Object with new values * @return {Object} New Object with updated values */ export const updateObject = (oldObject, updatedValues) => { return { ...oldObject, ...updatedValues }; };
Sie können es also so verwenden
const MyComponent = props => { const [orderForm, setOrderForm] = useState({ specialities: { elementType: "select", elementConfig: { options: [], label: "Specialities" }, touched: false } }); // I want to update the options list, to fill a select element // ---------- Update with fetched elements ---------- // const updateSpecialitiesData = data => { // Inmutably update elementConfig object. i.e label field is not modified const updatedOptions = updateObject( orderForm[formElementKey]["elementConfig"], { options: data } ); // Inmutably update the relevant element. const updatedFormElement = updateObject(orderForm[formElementKey], { touched: true, elementConfig: updatedOptions }); // Inmutably update the relevant element in the state. const orderFormUpdated = updateObject(orderForm, { [formElementKey]: updatedFormElement }); setOrderForm(orderFormUpdated); }; useEffect(() => { // some code to fetch data updateSpecialitiesData.current("specialities",fetchedData); }, [updateSpecialitiesData]); // More component code }
Wenn nicht, haben Sie hier weitere Dienstprogramme: https://es.reactjs.org/docs/update.html
quelle
Anfangs habe ich ein Objekt in useState verwendet, dann bin ich für komplexe Fälle zum useReducer-Hook übergegangen. Ich spürte eine Leistungsverbesserung, als ich den Code überarbeitete.
useReducer React-Dokumente
Ich habe einen solchen Hook bereits für meinen eigenen Gebrauch implementiert:
/** * Same as useObjectState but uses useReducer instead of useState * (better performance for complex cases) * @param {*} PropsWithDefaultValues object with all needed props * and their initial value * @returns [state, setProp] state - the state object, setProp - dispatch * changes one (given prop name & prop value) or multiple props (given an * object { prop: value, ...}) in object state */ export function useObjectReducer(PropsWithDefaultValues) { const [state, dispatch] = useReducer(reducer, PropsWithDefaultValues); //newFieldsVal={[field_name]: [field_value], ...} function reducer(state, newFieldsVal) { return { ...state, ...newFieldsVal }; } return [ state, (newFieldsVal, newVal) => { if (typeof newVal !== "undefined") { const tmp = {}; tmp[newFieldsVal] = newVal; dispatch(tmp); } else { dispatch(newFieldsVal); } }, ]; }
mehr verwandte Haken .
quelle