ReactJS : 자식 구성 요소 내부 부모의 setState TodoForm = React.createClass({ getInitialState: function() {

자식 구성 요소의 부모에서 setState를 수행하는 데 권장되는 패턴은 무엇입니까?

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)

부모의 상태로 유지되는 할 일 항목 배열이 있습니다. 부모의 상태에 액세스하고 TodoFormhandleClick구성 요소 에서 새 할 일 항목을 추가하고 싶습니다 . 내 생각은 부모에 대해 setState를 수행하여 새로 추가 된 할일 항목을 렌더링하는 것입니다.



답변

부모 addTodoItem에서 필요한 setState를 수행하는 함수를 만든 다음 해당 함수를 하위 구성 요소에 소품으로 전달할 수 있습니다.

var Todos = React.createClass({

  ...

  addTodoItem: function(todoItem) {
    this.setState(({ todos }) => ({ todos: { ...todos, todoItem } }));
  },

  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: ""});
  },

  ...

});

addTodoItemTodoForm의 handleClick에서 호출 할 수 있습니다 . 이것은 새로 추가 된 할일 항목을 렌더링 할 부모에 대한 setState를 수행합니다. 아이디어를 얻으시기 바랍니다.

여기 바이올린.


답변

이것들은 모두 본질적으로 정확합니다. 기본적으로 권장하는 새로운 공식 반응 문서를 가리킬 것이라고 생각했습니다.

React 애플리케이션에서 변경되는 모든 데이터에 대한 단일 “진실 소스”가 있어야합니다. 일반적으로 상태는 렌더링에 필요한 구성 요소에 먼저 추가됩니다. 그런 다음 다른 구성 요소도 필요하면 가장 가까운 공통 조상으로 들어 올릴 수 있습니다. 서로 다른 구성 요소간에 상태를 동기화하는 대신 하향식 데이터 흐름에 의존해야합니다.

https://reactjs.org/docs/lifting-state-up.html을 참조 하십시오 . 이 페이지는 예제를 통해서도 작동합니다.


답변

부모 구성 요소에 addTodo 함수를 만들고 해당 컨텍스트에 바인딩하고 자식 구성 요소에 전달하고 거기에서 호출 할 수 있습니다.

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

그런 다음 Todos.render에서 다음을 수행합니다.

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

TodoForm에서 이것을 호출하십시오.

this.props.addToDo(newTodo);


답변

React Hook으로 상태를 유지하는 사람들을 위해 useState위의 제안을 수정하여 아래의 데모 슬라이더 앱을 만들었습니다. 데모 앱에서 자식 슬라이더 구성 요소는 부모의 상태를 유지합니다.

데모에서는 useEffect후크 도 사용합니다 . (그리고 덜 중요한 것은 useRef후크)

import React, { useState, useEffect, useCallback, 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 = useCallback(val => {
    setParentState(val);
  }, [setParentState]);

  return (
    <div style={{ margin: 30 }}>
      <Child
        parentState={parentState}
        parentStateSetter={wrapperSetParentState}
      />
      <div>Parent State: {parentState}</div>
    </div>
  );
};

//the child react component
function Child({parentStateSetter}) {
  const childRef = useRef();
  const [childState, setChildState] = useState(0);

  useEffect(() => {
    parentStateSetter(childState);
  }, [parentStateSetter, 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;


답변

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


답변

하위 구성 요소에서 상위 구성 요소로 인수를 전달하는 다음과 같은 작동하고 간단한 솔루션을 찾았습니다.

//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")
    );
}

JSFIDDLE 좀 봐


답변

클래스 구성 요소를 부모로 사용하는 경우 setState를 자식에게 전달하는 매우 간단한 방법 중 하나는 화살표 함수 내에서 전달하는 것입니다. 이것은 통과 할 수있는 호이스트 된 환경을 설정함에 따라 작동합니다.

class ClassComponent ... {

    modifyState = () =>{
        this.setState({...})
    }
    render(){
          return <><ChildComponent parentStateModifier={modifyState} /></>
    }
}