programing

React JS: 부모 내부 자식 컴포넌트의 setState

closeapi 2023. 3. 27. 21:16
반응형

React JS: 부모 내부 자식 컴포넌트의 setState

자식 구성 요소에서 부모에 대해 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를 실행하여 새로 추가된 todo 항목을 렌더링하는 것이 제 생각입니다.

부모에게 다음과 같은 기능을 만들 수 있습니다.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: ""});
  },

  ...

});

호출할 수 있습니다.addTodoItem[ ToDoForm의 handleClick이렇게 하면 새로 추가된 작업 항목을 렌더링하는 부모에서 setState가 수행됩니다.이해하시길 바랍니다.

여기를 만지작거리다.

리액트 훅으로 상태를 유지하는 사용자용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;

이것들은 모두 기본적으로 옳습니다.저는 기본적으로 다음 사항을 권장하는 새로운 공식 반응 문서를 언급하려고 합니다.

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);

사용하시는 분useState안에서.Arrow Functional Components와 함께TypeScriptenabled, 다음은 부모 상태 설정기 함수를 자녀에게 전달하고 이를 호출하여 자녀로부터 적절한 시간에 부모 상태를 설정하는 간단한 예입니다.

샘플

상위 구성 요소:

import {useState} from "react";
const ParentComponent = () => {
  const [hasParentStateChange, setHasParentStateChange] = useState<boolean>(false);

  return (
      <div>
        Parent's view: {String(hasParentStateChange)}
        <ChildComponent
            hasParentStateChange={hasParentStateChange}
            setHasParentStateChange={setHasParentStateChange} // <---- Passing parent's state setter over
        />
      </div>
  );
}

하위 구성 요소:

interface PropsDefinition {
  hasParentStateChange: boolean;
  setHasParentStateChange(data: boolean): void;
}

const ChildComponent = (props: PropsDefinition) => {
  return (
      <div>
        <div>
          Child's view: {String(props.hasParentStateChange)}
        </div>
        <button
            onClick={() => props.setHasParentStateChange(!props.hasParentStateChange)} // <---- Invoking parent's state setter
        >
            Toggle parent state from child
        </button>
      </div>
  );
}
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")
    );
}

JSFIDLE 보기

클래스 컴포넌트를 부모로서 사용하고 있는 경우, setState를 자녀에게 전달하는 매우 간단한 방법 중 하나는 화살표 함수 내에서 전달하는 것입니다.이것은, 전달 가능한 highest 환경을 설정하기 위해서 기능합니다.

class ClassComponent ... {

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

언급URL : https://stackoverflow.com/questions/29100774/reactjs-setstate-on-parent-inside-child-component

반응형