programing

componentDidUpdate() 내의 setState()

css3 2023. 3. 1. 11:25

componentDidUpdate() 내의 setState()

드롭 다운의 높이와 화면상의 입력 위치에 따라 드롭 다운이 입력의 아래 또는 위쪽으로 이동하는 스크립트를 쓰고 있습니다.또한 방향성에 따라 수식자를 드롭다운으로 설정하고 싶습니다.단, 을 사용하여setState내부componentDidUpdate무한 루프 생성(명확한)

이 기능을 사용하는데서 해결책을 찾았습니다.getDOMNodeclassname을 직접 드롭다운으로 설정하지만 React 툴을 사용하여 더 나은 솔루션이 있을 것 같습니다.누가 나 좀 도와줄래?

다음은 다음 코드와 관련된 작업 코드입니다.getDOMNode(코드 심플화를 위해 위치추적 로직이 약간 무시되었습니다.

let SearchDropdown = React.createClass({
    componentDidUpdate(params) {
        let el = this.getDOMNode();
        el.classList.remove('dropDown-top');
        if(needToMoveOnTop(el)) {
            el.top = newTopValue;
            el.right = newRightValue;
            el.classList.add('dropDown-top');
        }
    },
    render() {
        let dataFeed = this.props.dataFeed;
        return (
            <DropDown >
                {dataFeed.map((data, i) => {
                    return (<DropDownRow key={response.symbol} data={data}/>);
                })}
            </DropDown>
        );
    }
});

여기 setstate 코드(무한 루프 생성)가 있습니다.

let SearchDropdown = React.createClass({
    getInitialState() {
        return {
            top: false
        };
    },
    componentDidUpdate(params) {
        let el = this.getDOMNode();
        if (this.state.top) {
           this.setState({top: false});
        }
        if(needToMoveOnTop(el)) {
            el.top = newTopValue;
            el.right = newRightValue;
            if (!this.state.top) {
              this.setState({top: true});
           }
        }
    },
    render() {
        let dataFeed = this.props.dataFeed;
        let class = cx({'dropDown-top' : this.state.top});
        return (
            <DropDown className={class} >
                {dataFeed.map((data, i) => {
                    return (<DropDownRow key={response.symbol} data={data}/>);
                })}
            </DropDown>
        );
    }
});

사용할 수 있습니다.setState안에서.componentDidUpdate문제는 브레이크 조건이 없기 때문에 무한 루프를 만들고 있다는 것입니다.

컴포넌트가 렌더링되면 브라우저에 의해 제공되는 값이 필요하다는 사실에 근거해, 저는 당신의 접근 방식이componentDidUpdate정답입니다.그것은 단지, 이 문제를 일으키는 상황을 보다 잘 처리할 필요가 있을 뿐입니다.setState.

componentDidUpdate시그니처는void::componentDidUpdate(previousProps, previousState)이를 통해 어떤 소품/상태가 더러운지 테스트할 수 있으며,setState따라서.

예:

componentDidUpdate(previousProps, previousState) {
    if (previousProps.data !== this.props.data) {
        this.setState({/*....*/})
    }
}

사용하시는 경우setState안에서.componentDidUpdate컴포넌트가 갱신되고 결과적으로 콜이 발생합니다.componentDidUpdate그 후에 콜을 합니다.setState다시 무한 루프가 발생합니다.당신은 조건부로 전화해야 합니다.setState콜을 위반하는 상태가 최종적으로 발생하는 것을 확인합니다.다음은 예를 제시하겠습니다.

componentDidUpdate: function() {
    if (condition) {
        this.setState({..})
    } else {
        //do something else
    }
}

컴포넌트에 소품을 보내는 것만으로 컴포넌트를 갱신하는 경우(componentDidUpdate 내부의 경우를 제외하고 setState에 의해 갱신되지 않음), 콜할 수 있습니다.setState안에서.componentWillReceiveProps대신componentDidUpdate.

예는 리액트 라이프 사이클 훅을 이해하는 데 도움이 됩니다.

넌 할 수 있다.setStategetDerivedStateFromProps방법, 즉, static그리고 소품 변경 후에 방법을 트리거합니다.componentDidUpdate.

componentDidUpdate다음에서 반환되는 세 번째 매개 변수를 얻을 수 있습니다.getSnapshotBeforeUpdate.

코드와 상자 링크를 확인할 수 있습니다.

// Child component
class Child extends React.Component {
  // First thing called when component loaded
  constructor(props) {
    console.log("constructor");
    super(props);
    this.state = {
      value: this.props.value,
      color: "green"
    };
  }

  // static method
  // dont have access of 'this'
  // return object will update the state
  static getDerivedStateFromProps(props, state) {
    console.log("getDerivedStateFromProps");
    return {
      value: props.value,
      color: props.value % 2 === 0 ? "green" : "red"
    };
  }

  // skip render if return false
  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate");
    // return nextState.color !== this.state.color;
    return true;
  }

  // In between before real DOM updates (pre-commit)
  // has access of 'this'
  // return object will be captured in componentDidUpdate
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate");
    return { oldValue: prevState.value };
  }

  // Calls after component updated
  // has access of previous state and props with snapshot
  // Can call methods here
  // setState inside this will cause infinite loop
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("componentDidUpdate: ", prevProps, prevState, snapshot);
  }

  static getDerivedStateFromError(error) {
    console.log("getDerivedStateFromError");
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log("componentDidCatch: ", error, info);
  }

  // After component mount
  // Good place to start AJAX call and initial state
  componentDidMount() {
    console.log("componentDidMount");
    this.makeAjaxCall();
  }

  makeAjaxCall() {
    console.log("makeAjaxCall");
  }

  onClick() {
    console.log("state: ", this.state);
  }

  render() {
    return (
      <div style={{ border: "1px solid red", padding: "0px 10px 10px 10px" }}>
        <p style={{ color: this.state.color }}>Color: {this.state.color}</p>
        <button onClick={() => this.onClick()}>{this.props.value}</button>
      </div>
    );
  }
}

// Parent component
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: 1 };

    this.tick = () => {
      this.setState({
        date: new Date(),
        value: this.state.value + 1
      });
    };
  }

  componentDidMount() {
    setTimeout(this.tick, 2000);
  }

  render() {
    return (
      <div style={{ border: "1px solid blue", padding: "0px 10px 10px 10px" }}>
        <p>Parent</p>
        <Child value={this.state.value} />
      </div>
    );
  }
}

function App() {
  return (
    <React.Fragment>
      <Parent />
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

주(州)가 이미 당신이 설정하려는 것과 동일한 값을 가지고 있는지 확인해야 합니다.같은 값일 경우 동일한 값에 대해 상태를 다시 설정할 필요가 없습니다.

상태를 다음과 같이 설정하십시오.

let top = newValue /*true or false*/
if(top !== this.state.top){
    this.setState({top});
}

this.setState는 루프에 브레이크 조건이 없는 경우 ComponentDidUpdate에서 사용하면 무한 루프를 생성합니다.redex를 사용하여 if 스테이트먼트에서 변수를 true로 설정한 후 변수를 false로 설정한 조건에서 변수가 작동합니다.

이런 거.

if(this.props.route.params.resetFields){

        this.props.route.params.resetFields = false;
        this.setState({broadcastMembersCount: 0,isLinkAttached: false,attachedAffiliatedLink:false,affilatedText: 'add your affiliate link'});
        this.resetSelectedContactAndGroups();
        this.hideNext = false;
        this.initialValue_1 = 140;
        this.initialValue_2 = 140;
        this.height = 20
    }

나도 비슷한 문제에 직면했다.componentDidUpdate를 화살표 함수로 만드십시오.그러면 되겠군요.

componentDidUpdate = (params) => {
    let el = this.getDOMNode();
    if (this.state.top) {
       this.setState({top: false});
    }
    if(needToMoveOnTop(el)) {
        el.top = newTopValue;
        el.right = newRightValue;
        if (!this.state.top) {
          this.setState({top: true});
       }
    }
}

toolTip을 중앙에 배치해야 하는 유사한 문제가 있었습니다.componentDidUpdate의 react setState가 무한 루프 상태가 되어 동작하는 조건을 시험했습니다.그러나 ref 콜백을 사용하면 보다 간단하고 깔끔한 솔루션이 제공되므로 ref 콜백에 인라인 함수를 사용하면 모든 컴포넌트 업데이트에 대해 null 문제가 발생합니다.따라서 참조 콜백에서 함수 참조를 사용하고 상태를 설정합니다. 그러면 재렌더가 시작됩니다.

setState inside componentDidUpdate를 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/30528348/setstate-inside-of-componentdidupdate