IT

React에서 부모의 상태를 업데이트하는 방법은 무엇입니까?

lottoking 2020. 3. 22. 10:52
반응형

React에서 부모의 상태를 업데이트하는 방법은 무엇입니까?


내 구조는 다음과 같습니다.

Component 1  

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5  

Component 3

구성 요소 3은 구성 요소 5의 상태에 따라 일부 데이터를 표시해야합니다. 소품은 변경할 수 없으므로 단순히 구성 요소 1의 상태를 저장 한 다음 전달할 수 없습니다. 그리고 예, 나는 redux에 대해 읽었지만 그것을 사용하고 싶지 않습니다. 반응만으로 해결할 수 있기를 바랍니다. 내가 잘못?


자녀-부모 의사 소통을 위해 다음과 같이 부모에서 자녀로 상태를 설정하는 함수를 전달해야합니다.

class Parent extends React.Component {
  constructor(props) {
    super(props)

    this.handler = this.handler.bind(this)
  }

  handler(someValue) {
    this.setState({
      someVar: someValue
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

이런 식으로 자식은 소품과 함께 전달 된 함수의 호출로 부모의 상태를 업데이트 할 수 있습니다.

그러나 구성 요소 5와 3은 관련이 없기 때문에 구성 요소의 구조를 재고해야합니다.

가능한 해결책 중 하나는 컴포넌트 1과 3의 상태를 모두 포함하는 상위 레벨 컴포넌트로 랩핑하는 것입니다.이 컴포넌트는 소품을 통해 하위 레벨 상태를 설정합니다.


자식에서 부모 구성 요소로 onClick 함수 인수를 전달하는 다음 작업 솔루션을 찾았습니다.

메소드를 전달하는 버전 ()

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}

//ParentA component
class ParentA extends React.Component {

    constructor(props) {
        super(props);
        var handleToUpdate  = this.handleToUpdate.bind(this);
        var arg1 = '';
    }

    handleToUpdate(someArg){
            alert('We pass argument from Child to Parent: ' + someArg);
            this.setState({arg1:someArg});
    }

    render() {
        var handleToUpdate  =   this.handleToUpdate;

        return (<div>
                    <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

JSFIDDLE을보십시오

화살표 함수를 전달하는 버전

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div>
          <button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}

//ParentA component
class ParentA extends React.Component { 
    constructor(props) {
        super(props);
    }

    handleToUpdate = (someArg) => {
            alert('We pass argument from Child to Parent: ' + someArg);
    }

    render() {
        return (<div>
            <ChildB handleToUpdate = {this.handleToUpdate} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

JSFIDDLE을보십시오


나는 함수를 전달하는 것에 대한 대답, 매우 편리한 기술을 좋아합니다.

On the flip side you can also achieve this using pub/sub or using a variant, a dispatcher, as Flux does. The theory is super simple, have component 5 dispatch a message which component 3 is listening for. Component 3 then updates its state which triggers the re-render. This requires stateful components, which, depending on your viewpoint, may or may not be an anti-pattern. I'm against them personally and would rather that something else is listening for dispatches and changes state from the very top-down (Redux does this, but adds additional terminology).

import { Dispatcher } from flux
import { Component } from React

const dispatcher = new Dispatcher()

// Component 3
// Some methods, such as constructor, omitted for brevity
class StatefulParent extends Component {
  state = {
    text: 'foo'
  } 

  componentDidMount() {
    dispatcher.register( dispatch => {
      if ( dispatch.type === 'change' ) {
        this.setState({ text: 'bar' })
      }
    }
  }

  render() {
    return <h1>{ this.state.text }</h1>
  }
}

// Click handler
const onClick = event => {
  dispatcher.dispatch({
    type: 'change'
  })
}

// Component 5 in your example
const StatelessChild = props => {
  return <button onClick={ onClick }>Click me</button> 
}

Flux가 포함 된 디스패처 번들은 매우 간단합니다. 디스패치의 내용을 전달하여 디스패치가 발생할 때 콜백을 등록하고 호출합니다 (위의 간결한 예제에는 payload메시지 ID가 없음). 당신이 더 합리적이라면 전통적인 펍 / 서브 (예를 들어, 이벤트에서 EventEmitter를 사용하거나 다른 버전으로)에 이것을 쉽게 조정할 수 있습니다.


기본적으로 화살표 기능을 사용하여 내 문제에 대한 아이디어를 제공하고 하위 구성 요소에서 매개 변수를 전달한 것에 대한 가장 큰 대답을 고맙게 생각합니다.

 class Parent extends React.Component {
  constructor(props) {
    super(props)
    // without bind, replaced by arrow func below
  }

  handler = (val) => {
    this.setState({
      someVar: val
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {() => this.props.handler('the passing value')}/ >
  }
}

그것이 누군가를 돕기를 바랍니다.


param을 사용하여 자식에서 부모 구성 요소로 onClick 함수 인수를 전달하는 다음 작업 솔루션을 찾았습니다.

부모 클래스 :

class Parent extends React.Component {
constructor(props) {
    super(props)

    // Bind the this context to the handler function
    this.handler = this.handler.bind(this);

    // Set some state
    this.state = {
        messageShown: false
    };
}

// This method will be sent to the child component
handler(param1) {
console.log(param1);
    this.setState({
        messageShown: true
    });
}

// Render the child component and set the action property with the handler as value
render() {
    return <Child action={this.handler} />
}}

어린이 수업 :

class Child extends React.Component {
render() {
    return (
        <div>
            {/* The button will execute the handler function set by the parent component */}
            <Button onClick={this.props.action.bind(this,param1)} />
        </div>
    )
} }

어느 수준에서든 자녀와 부모 사이의 의사 소통이 필요할 때마다 context를 사용하는 것이 좋습니다 . 상위 컴포넌트에서 다음과 같이 하위에서 호출 할 수있는 컨텍스트를 정의하십시오.

사례 구성 요소 3의 상위 구성 요소

static childContextTypes = {
        parentMethod: React.PropTypes.func.isRequired
      };

       getChildContext() {
        return {
          parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child)
        };
      }

parentMethod(parameter_from_child){
// update the state with parameter_from_child
}

이제 하위 구성 요소 (귀하의 경우 구성 요소 5) 에서이 구성 요소에 부모의 컨텍스트를 사용하고 싶다고 알려주십시오.

 static contextTypes = {
       parentMethod: React.PropTypes.func.isRequired
     };
render(){
    return(
      <TouchableHighlight
        onPress={() =>this.context.parentMethod(new_state_value)}
         underlayColor='gray' >   

            <Text> update state in parent component </Text>              

      </TouchableHighlight>
)}

repo 에서 데모 프로젝트를 찾을 수 있습니다


react가 단방향 데이터 흐름을 촉진함에 따라 부모에서 자식으로 만 데이터를 전달할 수 있지만 "자식 구성 요소"에서 무언가가 발생할 때 부모를 자체적으로 업데이트하기 위해 일반적으로 "콜백 함수"를 사용합니다.

부모에 정의 된 함수를 자식에 "props"로 전달하고 해당 함수를 자식 구성 요소에서 트리거하는 자식 함수에서 호출합니다.


class Parent extends React.Component {
  handler = (Value_Passed_From_SubChild) => {
    console.log("Parent got triggered when a grandchild button was clicked");
    console.log("Parent->Child->SubChild");
    console.log(Value_Passed_From_SubChild);
  }
  render() {
    return <Child handler = {this.handler} />
  }
}
class Child extends React.Component {
  render() {
    return <SubChild handler = {this.props.handler}/ >
  }
}
class SubChild extends React.Component { 
  constructor(props){
   super(props);
   this.state = {
      somethingImp : [1,2,3,4]
   }
  }
  render() {
     return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
  }
}
React.render(<Parent />,document.getElementById('app'));

 HTML
 ----
 <div id="app"></div>

이 예에서 함수를 직접 Child에 전달하여 SubChild-> Child-> Parent에서 데이터를 전달할 수 있습니다.


-ParentComponent를 만들고 handleInputChange 메소드를 사용하여 ParentComponent 상태를 업데이트 할 수 있습니다. ChildComponent를 임포트하면 부모에서 자식 컴포넌트로 두 개의 props를 전달합니다.

import React, { Component } from 'react';
import ChildComponent from './ChildComponent';

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.state = {
      count: '',
    };
  }

  handleInputChange(e) {
    const { value, name } = e.target;
    this.setState({ [name]: value });
  }

  render() {
    const { count } = this.state;
    return (
      <ChildComponent count={count} handleInputChange={this.handleInputChange} />
    );
  }
}
  • 이제 ChildComponent 파일을 만들고 ChildComponent.jsx로 저장합니다. 하위 구성 요소에 상태가 없기 때문에이 구성 요소는 상태 비 저장입니다. 소품 유형 검사에는 prop-types 라이브러리를 사용합니다.

    import React from 'react';
    import { func, number } from 'prop-types';
    
    const ChildComponent = ({ handleInputChange, count }) => (
      <input onChange={handleInputChange} value={count} name="count" />
    );
    
    ChildComponent.propTypes = {
      count: number,
      handleInputChange: func.isRequired,
    };
    
    ChildComponent.defaultProps = {
      count: 0,
    };
    
    export default ChildComponent;
    

이 페이지에서 최고 등급의 답변을 여러 번 사용했지만 React를 배우는 동안 소품 내부의 바인딩과 인라인 기능없이이를 수행하는 더 좋은 방법을 찾았습니다.

여기를보세요 :

class Parent extends React.Component {

  constructor() {
    super();
    this.state={
      someVar: value
    }
  }

  handleChange=(someValue)=>{
    this.setState({someVar: someValue})
  }

  render() {
    return <Child handler={this.handleChange} />
  }

}

export const Child = ({handler}) => {
  return <Button onClick={handler} />
}

키는 화살표 기능입니다.

handleChange=(someValue)=>{
  this.setState({someVar: someValue})
}

자세한 내용은 여기를 참조 하십시오 . 희망이 이것이 누군가에게 유용 할 것입니다 =)


따라서 상위 구성 요소를 업데이트하려는 경우

 class ParentComponent extends React.Component {
        constructor(props){
            super(props);
            this.state = {
               page:0
            }
        }

        handler(val){
            console.log(val) // 1
        }

        render(){
          return (
              <ChildComponent onChange={this.handler} />
           )
       }
   }


class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
             page:1
        };
    }

    someMethod = (page) => {
        this.setState({ page: page });
        this.props.onChange(page)
    }

    render() {
        return (
       <Button
            onClick={() => this.someMethod()} 
       > Click
        </Button>
      )
   }
}

여기서 onChange는 "handler"메소드가 인스턴스에 바인딩 된 속성입니다. props 인수에서 onChange 속성을 통해 수신하도록 메소드 핸들러를 Child 클래스 컴포넌트에 전달했습니다.

onChange 속성은 다음과 같이 props 객체에 설정됩니다.

props ={
onChange : this.handler
}

자식 구성 요소로 전달

따라서 Child 구성 요소는 props.onChange와 같은 props 객체의 name 값에 액세스 할 수 있습니다.

렌더링 소품을 사용하여 수행됩니다.

이제 Child 컴포넌트에는 props 인수 객체에서 onChnge를 통해 전달 된 핸들러 메소드를 호출하기 위해 onclick 이벤트가 설정된 "Click"버튼이 있습니다. 이제 Child의 this.props.onChange는 Parent 클래스 Reference 및 credits : Bits and Pieces에 출력 메소드를 보유합니다 .


이 같은 시나리오가 어디에나 분산되어 있지 않은 경우, 특히 상태 관리 라이브러리가 도입하는 모든 오버 헤드를 도입하지 않으려는 경우 React의 컨텍스트를 사용할 수 있습니다. 또한 배우기가 더 쉽습니다. 그러나 조심해서 사용하면 나쁜 코드를 작성할 수 있습니다. 기본적으로 컨테이너 구성 요소를 정의하면 (그 상태를 유지하고 유지할 것입니다) 모든 구성 요소가 해당 데이터 조각을 자식으로 쓰거나 읽는 데 관심이 있습니다 (직접 자식은 아님)

https://reactjs.org/docs/context.html

대신 일반 반응을 올바르게 사용할 수도 있습니다.

<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />

컴포넌트 1까지 doSomethingAbout5를 전달하십시오.

    <Component1>
        <Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
        <Component5 propThatDependsOn5={this.state.somethingAbout5}/>
    <Component1/>

이것이 일반적인 문제라면 응용 프로그램의 전체 상태를 다른 곳으로 옮기는 것을 생각해야합니다. 몇 가지 옵션이 있으며 가장 일반적인 옵션은 다음과 같습니다.

https://redux.js.org/

https://facebook.github.io/flux/

기본적으로 구성 요소에서 응용 프로그램 상태를 관리하는 대신 상태가 업데이트 될 때 명령을 보냅니다. 구성 요소는이 컨테이너에서 상태를 가져와 모든 데이터가 중앙 집중화됩니다. 이것은 더 이상 로컬 상태를 사용할 수 없다는 것을 의미하지는 않지만 더 고급 주제입니다.


<Footer 
  action={()=>this.setState({showChart: true})}
/>

<footer className="row">
    <button type="button" onClick={this.props.action}>Edit</button>
  {console.log(this.props)}
</footer>

Try this example to write inline setState, it avoids creating another function.

참고 URL : https://stackoverflow.com/questions/35537229/how-to-update-parents-state-in-react

반응형