부모 상태 변경 후 React 자식 구성 요소가 업데이트되지 않음


109

다양한 하위 구성 요소에 데이터를 채우기 위해 멋진 ApiWrapper 구성 요소를 만들려고합니다. 내가 읽은 모든 것에서 이것은 작동합니다 : https://jsfiddle.net/vinniejames/m1mesp6z/1/

class ApiWrapper extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      response: {
        "title": 'nothing fetched yet'
      }
    };
  }

  componentDidMount() {
    this._makeApiCall(this.props.endpoint);
  }

  _makeApiCall(endpoint) {
    fetch(endpoint).then(function(response) {
      this.setState({
        response: response
      });
    }.bind(this))
  }

  render() {
    return <Child data = {
      this.state.response
    }
    />;
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: props.data
    };
  }

  render() {
    console.log(this.state.data, 'new data');
    return ( < span > {
      this.state.data.title
    } < /span>);
  };
}

var element = < ApiWrapper endpoint = "https://jsonplaceholder.typicode.com/posts/1" / > ;

ReactDOM.render(
  element,
  document.getElementById('container')
);

그러나 어떤 이유로 부모 상태가 변경 될 때 자식 구성 요소가 업데이트되지 않는 것 같습니다.

여기에 뭔가 빠졌나요?

답변:


205

코드에 두 가지 문제가 있습니다.

자식 구성 요소의 초기 상태는 소품에서 설정됩니다.

this.state = {
  data: props.data
};

SO 응답 에서 인용 :

초기 상태를 구성 요소에 전달하는 prop것은 안티 패턴입니다. 왜냐하면 getInitialState(우리의 경우 생성자) 메서드는 구성 요소가 처음 렌더링 될 때만 호출 되기 때문 입니다. 더 이상. 즉, 다른 값을로 전달하는 해당 구성 요소를 다시 렌더링하면 구성 prop요소가 처음 렌더링되었을 때의 상태를 유지하므로 구성 요소가 그에 따라 반응하지 않습니다. 오류가 발생하기 쉽습니다.

따라서 이러한 상황을 피할 수없는 경우 이상적인 솔루션은 방법 componentWillReceiveProps을 사용하여 새 소품을 수신하는 것입니다.

아래 코드를 자식 구성 요소에 추가하면 자식 구성 요소 다시 렌더링 문제가 해결됩니다.

componentWillReceiveProps(nextProps) {
  this.setState({ data: nextProps.data });  
}

두 번째 문제는 fetch.

_makeApiCall(endpoint) {
  fetch(endpoint)
    .then((response) => response.json())   // ----> you missed this part
    .then((response) => this.setState({ response }));
}

그리고 여기에 작동하는 바이올린이 있습니다 : https://jsfiddle.net/o8b04mLy/


1
" 무엇을하는지 안다면 props를 기반으로 상태초기화하는 것은 괜찮습니다. " nextProp없이 re-render를 트리거하지 않는다는 사실 외에 prop를 통한 상태 설정에 대한 다른 단점이 componentWillReceiveProps(nextProps)있습니까?
Vinnie James

11
내가 아는 한 다른 단점은 없습니다. 그러나 귀하의 경우에는 자식 구성 요소 내부에 상태를 갖는 것을 분명히 피할 수 있습니다. 부모는 데이터를 소품으로 전달할 수 있으며 부모가 새 상태로 다시 렌더링하면 자식도 다시 렌더링됩니다 (새 소품으로). 실제로 여기에서는 아이의 내부 상태를 유지할 필요가 없습니다. 순수한 구성 요소 FTW!
Yadhu Kiran

7
지금부터 읽는 사람은 static getDerivedStateFromProps(nextProps, prevState) reactjs.org/docs/…를
GoatsWearHats

4
이제 더 이상 사용되지 않기 때문에 componentWillReceiveProps () 이외의 다른 솔루션이 있습니까?
LearningMath

3
@LearningMath 는 대체 방법에 대해 설명 하는 최신 React 문서 를 참조하십시오 . 논리를 재고해야 할 수도 있습니다.
Yadhu Kiran 2018

1

변경해야 할 사항이 있습니다.

fetch응답을 받으면 json이 아닙니다. 이 json을 어떻게 얻을 수 있는지 찾고 있었는데이 링크를 발견했습니다 .

반면에 constructor함수는 한 번만 호출 된다고 생각할 필요가 있습니다.

따라서 <Child>컴포넌트 에서 데이터를 검색하는 방식을 변경해야합니다 .

여기에 예제 코드를 남겼습니다 : https://jsfiddle.net/emq1ztqj/

도움이 되었기를 바랍니다.


감사합니다. 비록, 당신이 만든 예제를 보면 여전히 Child가 업데이트하지 않는 것처럼 보입니다. 자녀가 데이터를받는 방식을 변경하는 방법에 대한 제안이 있습니까?
비니 제임스

2
확실합니까? 그 참조 <Child>구성 요소에서 새 데이터를 검색 https://jsonplaceholder.typicode.com/posts/1및 재 렌더링 할.
slorenzo

1
예, 이제 OSX에서 작동합니다. 아이폰 OS는하여 StackExchange 응용 브라우저에 re-렌더링 트리거 않네
비니 제임스에게
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.