update react props component actualizar reactjs

reactjs - props - setstate react js



ReactJS: setState en padre dentro del componente hijo (6)

¿Cuál es el patrón recomendado para hacer un setState en un elemento primario desde un componente secundario?

var Todos = React.createClass({ getInitialState: function() { return { todos: [ "I am done", "I am not done" ] } }, render: function() { var todos = this.state.todos.map(function(todo) { return <div>{todo}</div>; }); return <div> <h3>Todo(s)</h3> {todos} <TodoForm /> </div>; } }); var TodoForm = React.createClass({ getInitialState: function() { return { todoInput: "" } }, handleOnChange: function(e) { e.preventDefault(); this.setState({todoInput: e.target.value}); }, handleClick: function(e) { e.preventDefault(); //add the new todo item }, render: function() { return <div> <br /> <input type="text" value={this.state.todoInput} onChange={this.handleOnChange} /> <button onClick={this.handleClick}>Add Todo</button> </div>; } }); React.render(<Todos />, document.body)

Tengo una matriz de elementos de tareas pendientes que se mantiene en el estado de los padres. Quiero acceder al estado de los padres y agregar un nuevo elemento de TodoForm , desde el componente handleClick . Mi idea es hacer un setState en el padre, que representará el elemento de tarea recién agregado.


En su padre, puede crear una función como addTodoItem que hará el setState requerido y luego pasará esa función como accesorios al componente hijo.

var Todos = React.createClass({ ... addTodoItem: function(todoItem) { this.state.todos.push(todoItem); this.setState({todos: this.state.todos}); }, render: function() { ... return <div> <h3>Todo(s)</h3> {todos} <TodoForm addTodoItem={this.addTodoItem} /> </div> } }); var TodoForm = React.createClass({ handleClick: function(e) { e.preventDefault(); this.props.addTodoItem(this.state.todoInput); this.setState({todoInput: ""}); }, ... });

Puede invocar addTodoItem en TodoForm''s handleClick. Esto hará un setState en el padre que representará el elemento de tarea recién agregado. Espero que tengas la idea.

Violín aquí.


Encontré la siguiente solución funcional y simple para pasar argumentos de un componente secundario al componente primario:

//ChildExt component class ChildExt extends React.Component { render() { var handleForUpdate = this.props.handleForUpdate; return (<div><button onClick={() => handleForUpdate(''someNewVar'')}>Push me</button></div> ) } } //Parent component class ParentExt extends React.Component { constructor(props) { super(props); var handleForUpdate = this.handleForUpdate.bind(this); } handleForUpdate(someArg){ alert(''We pass argument from Child to Parent: /n'' + someArg); } render() { var handleForUpdate = this.handleForUpdate; return (<div> <ChildExt handleForUpdate = {handleForUpdate.bind(this)} /></div>) } } if(document.querySelector("#demo")){ ReactDOM.render( <ParentExt />, document.querySelector("#demo") ); }

Mira JSFIDDLE


Para aquellos que mantienen el estado con React Hook useState , useState las sugerencias anteriores para hacer una aplicación de control deslizante de demostración a continuación. En la aplicación de demostración, el componente de control deslizante secundario mantiene el estado de los padres.

La demostración también usa el gancho useEffect . (y menos importante, useRef gancho useRef )

import React, { useState, useEffect, useRef } from "react"; //the parent react component function Parent() { // the parentState will be set by its child slider component const [parentState, setParentState] = useState(0); // make wrapper function to give child const wrapperSetParentState = val => { setParentState(val); }; return ( <div style={{ margin: 30 }}> <Child parentState={parentState} parentStateSetter={wrapperSetParentState} /> <div>Parent State: {parentState}</div> </div> ); }; //the child react component function Child(props) { const childRef = useRef(); const [childState, setChildState] = useState(0); useEffect(() => { props.parentStateSetter(childState); }, [childState]); const onSliderChangeHandler = e => { //pass slider''s event value to child''s state setChildState(e.target.value); }; return ( <div> <input type="range" min="1" max="255" value={childState} ref={childRef} onChange={onSliderChangeHandler} ></input> </div> ); }; export default Parent;


Puede crear una función addTodo en el componente primario, vincularla a ese contexto, pasarla al componente secundario y llamarla desde allí.

// in Todos addTodo: function(newTodo) { // add todo }

Luego, en Todos.render, harías

<TodoForm addToDo={this.addTodo.bind(this)} />

Llama a esto en TodoForm con

this.props.addToDo(newTodo);


Todo esto es esencialmente correcto, solo pensé en señalar la nueva (oficial) documentación de reacción oficial que básicamente recomienda:

Debe haber una única "fuente de verdad" para cualquier dato que cambie en una aplicación React. Por lo general, el estado se agrega primero al componente que lo necesita para la representación. Luego, si otros componentes también lo necesitan, puede elevarlo hasta su ancestro común más cercano. En lugar de intentar sincronizar el estado entre diferentes componentes, debe confiar en el flujo de datos de arriba hacia abajo.

Ver https://reactjs.org/docs/lifting-state-up.html . La página también funciona a través de un ejemplo.


parentSetState={(obj) => { this.setState(obj) }}