[javascript] React에서 후크를 사용하여 컴포넌트를 강제로 다시 렌더링하려면 어떻게해야합니까?

아래 후크 예제 고려

   import { useState } from 'react';

   function Example() {
       const [count, setCount] = useState(0);

       return (
           <div>
               <p>You clicked {count} times</p>
               <button onClick={() => setCount(count + 1)}>
                  Click me
               </button>
          </div>
        );
     }

기본적으로 this.forceUpdate () 메서드를 사용하여 아래 예제와 같이 React 클래스 구성 요소에서 구성 요소를 즉시 다시 렌더링하도록합니다.

    class Test extends Component{
        constructor(props){
             super(props);
             this.state = {
                 count:0,
                 count2: 100
             }
             this.setCount = this.setCount.bind(this);//how can I do this with hooks in functional component 
        }
        setCount(){
              let count = this.state.count;
                   count = count+1;
              let count2 = this.state.count2;
                   count2 = count2+1;
              this.setState({count});
              this.forceUpdate();
              //before below setState the component will re-render immediately when this.forceUpdate() is called
              this.setState({count2: count
        }

        render(){
              return (<div>
                   <span>Count: {this.state.count}></span>.
                   <button onClick={this.setCount}></button>
                 </div>
        }
 }

하지만 내 쿼리는 위의 기능 구성 요소를 후크로 즉시 다시 렌더링하도록 강제 할 수 있습니까?



답변

내부적으로 사용하기 때문에 useState또는 으로 가능합니다 .useReduceruseStateuseReducer

const [, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({}), []);

forceUpdate정상적인 상황에서 사용하기위한 것이 아니라 테스트 또는 기타 뛰어난 경우에만 사용할 수 있습니다. 이 상황은보다 일반적인 방법으로 해결할 수 있습니다.

setCount부적절한 사용의 예입니다 forceUpdate, setState성능상의 이유로 비동기 및 상태 업데이트가 제대로 수행되지 않았다해서 동기로 강제되어서는 안된다. 상태가 이전에 설정된 상태에 의존하는 경우 업데이트 기능 으로 수행해야합니다 .

이전 상태를 기반으로 상태를 설정해야하는 경우 아래 업데이트 프로그램 인수에 대해 읽어보세요.

<…>

업데이터 함수에서 수신 한 상태와 소품은 모두 최신 상태를 보장합니다. 업데이트 프로그램의 출력은 상태와 얕게 병합됩니다.

setCount 목적이 불명확하기 때문에 예시가 아닐 수 있지만 이것은 업데이트 프로그램 기능의 경우입니다.

setCount(){
  this.setState(({count}) => ({ count: count + 1 }));
  this.setState(({count2}) => ({ count2: count + 1 }));
  this.setState(({count}) => ({ count2: count + 1 }));
}

이것은 콜백으로 사용되는 함수를 더 잘 기억해야한다는 점을 제외하고는 후크로 1 : 1로 변환됩니다.

   const [state, setState] = useState({ count: 0, count2: 100 });

   const setCount = useCallback(() => {
     setState(({count}) => ({ count: count + 1 }));
     setState(({count2}) => ({ count2: count + 1 }));
     setState(({count}) => ({ count2: count + 1 }));
   }, []);


답변

다른 사람들이 언급했듯이 useState작동합니다. mobx-react-lite 가 업데이트를 구현 하는 방법 은 다음과 같습니다. 유사한 작업을 수행 할 수 있습니다.

새 후크 정의, useForceUpdate

import { useState, useCallback } from 'react'

export function useForceUpdate() {
  const [, setTick] = useState(0);
  const update = useCallback(() => {
    setTick(tick => tick + 1);
  }, [])
  return update;
}

구성 요소에서 사용-

const forceUpdate = useForceUpdate();
if (...) {
  forceUpdate(); // force re-render
}

참조 https://github.com/mobxjs/mobx-react-lite/blob/master/src/utils.tshttps://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver .ts


답변

일반적으로 업데이트를 트리거하려는 모든 상태 처리 방법을 사용할 수 있습니다.

TypeScript 사용

codesandbox 예

useState

const forceUpdate: () => void = React.useState()[1].bind(null, {})  // see NOTE below

useReducer

const forceUpdate = React.useReducer(() => ({}), {})[1] as () => void

커스텀 후크로

이처럼 선호하는 접근 방식을 포장하십시오.

function useForceUpdate(): () => void {
  return React.useReducer(() => ({}), {})[1] as () => void // <- paste here
}

어떻게 작동합니까?

업데이트를 트리거하려면 은 어떤 값이 변경되었으며 컴포넌트를 다시 렌더링해야한다고 React 엔진에 알리는 것을 의미합니다.

[, setState]from useState()에는 매개 변수 가 필요합니다. 새로운 객체를 바인딩하여 제거합니다 {}.
() => ({})in useReducer은 액션이 전달 될 때마다 새로운 객체를 반환하는 더미 감속기입니다.
{} (새 객체) 는 상태에서 참조를 변경하여 업데이트를 트리거하기 위해 필요합니다.

추신 : 내부적으로 useState포장 useReducer합니다. 출처

참고 : useState와 함께 .bind를 사용하면 렌더링간에 함수 참조가 변경됩니다. 여기 에서이미 설명했듯이 useCallback 안에 넣을수는 있지만 섹시한 one-liner ™ 는 아닙니다. Reducer 버전은 이미 렌더링간에 참조 동등성을 유지 합니다. props에서 forceUpdate 함수를 전달하려는 경우 중요합니다.

일반 JS

const forceUpdate = React.useState()[1].bind(null, {})  // see NOTE above
const forceUpdate = React.useReducer(() => ({}))[1]


답변

@MinhKha의 답변에 대한 대안 :

다음으로 훨씬 더 깨끗해질 수 있습니다 useReducer.

const [, forceUpdate] = useReducer(x => x + 1, 0);

사용법 :
forceUpdate()-매개 변수없는 클리너


답변

다음과 같이 useState를 간단히 정의 할 수 있습니다.

const [, forceUpdate] = React.useState(0);

그리고 사용법 : forceUpdate(n => !n)

이 도움을 바랍니다!


답변

React Hooks FAQ 공식 솔루션 forceUpdate:

const [_, forceUpdate] = useReducer((x) => x + 1, 0);
// usage
<button onClick={forceUpdate}>Force update</button>

작업 예


답변

구성 요소가 상태 및 소품에만 의존하도록하는 것이 바람직하며 예상대로 작동하지만 구성 요소를 강제로 다시 렌더링하는 함수가 필요한 경우 다음을 사용할 수 있습니다. useState 하는 함수가 필요한 경우 후크를 필요할 때 함수를 호출 .

const { useState, useEffect } = React;

function Foo() {
  const [, forceUpdate] = useState();

  useEffect(() => {
    setTimeout(forceUpdate, 2000);
  }, []);

  return <div>{Date.now()}</div>;
}

ReactDOM.render(<Foo />, document.getElementById("root"));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>