programing

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

sourcejob 2023. 2. 16. 21:37
반응형

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

기본적으로 우리는 이것을 사용한다.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 ★★★★★★★★★★★★★★★★★」useReducer는 내부적으로 다음과 같이 사용합니다.

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

forceUpdate정상적인 상황에서는 사용할 수 없습니다. 테스트나 기타 미해결 상황에서만 사용할 수 있습니다.이 상황은 좀 더 전통적인 방법으로 다루어질 수 있다.

setCount한 사용 예시로, 을 참조해당 에서는, 을 참조해 주세요.forceUpdate,setState는 퍼포먼스상의 이유로 비동기이며 상태 갱신이 올바르게 실행되지 않았다고 해서 강제로 동기화할 수 없습니다.상태가 이전에 설정된 상태에 의존하는 경우 업데이트 프로그램 기능을 사용하여 수행해야 합니다.

이전 상태를 기준으로 상태를 설정해야 하는 경우 아래 updater 인수에 대해 읽어보십시오.

<...>

업데이터 기능으로 수신된 상태 및 소품 모두 최신 상태로 유지됩니다.업데이트 프로그램의 출력이 상태와 얄팍하게 병합됩니다.

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 }));
   }, []);

React Hooks FAQ 공식 솔루션:forceUpdate:

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

작업 예

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

  return (
    <div>
      <button onClick={forceUpdate}>Force update</button>
      <p>Forced update {_} times</p>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.1/umd/react.production.min.js" integrity="sha256-vMEjoeSlzpWvres5mDlxmSKxx6jAmDNY4zCt712YCI0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.1/umd/react-dom.production.min.js" integrity="sha256-QQt6MpTdAD0DiPLhqhzVyPs1flIdstR4/R7x4GqCvZ4=" crossorigin="anonymous"></script>
<script>var useReducer = React.useReducer</script>
<div id="root"></div>

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

TypeScript 사용

코드 앤 박스 예시

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]부에서useState()매개 변수를 필요로 합니다.에는 파라미터가 필요합니다.우리는 신선한 물체 는 로 체 음 것 거 을 object we get제 a그다한묶 it of rid써 by물새 binding우로 fresh으리운를 object we get..{}.
() => ({})useReducer는 액션이 디스패치될 때마다 새로운 오브젝트를 반환하는 더미 리듀서입니다.
{} 상태 내의 참조를 변경하여 업데이트를 트리거하기 위해 (오브젝트)가 필요합니다.

PS:useStateuseReducer복잡함을 줄이기 위해 환원제를 사용합니다.

메모: 기준 불안정성

「」를 사용합니다..binduseState이치
에 넣을 수도 있어요.useCallback여기 이 답변에서 이미 설명했듯이, 섹시한 원라이너는 아닐 것입니다.Reducer 버전은 이미 렌더링 간의 참조 평등(안정성)을 유지하고 있습니다.이것은 소품 내의 forceUpdate 함수를 다른 컴포넌트에 전달하는 경우에 중요합니다.

플레인 JS

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

다른 사람들이 언급했듯이useStatemobx-syslog-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.ts 및 https://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver.ts 를 참조해 주세요.

@MinhKha의 답변 대신:

를 사용하면 훨씬 깨끗해질 수 있습니다.useReducer:

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

: 사법 usage :forceUpdate()- 파라멜이 없는 클리너

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

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

★★★★forceUpdate(n => !n)

이게 도움이 되길 바라!

를 강제로 이 꼭 는, 을 할 수 .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>

심플 코드

const forceUpdate = React.useReducer(bool => !bool)[1];

용도:

forceUpdate();

은 특정 입니다.key이 트리거 됩니다. 키를 업데이트하면 컴포넌트의 렌더링이 트리거됩니다(이전에는 업데이트하지 못했습니다).

예를 들어 다음과 같습니다.

const [tableKey, setTableKey] = useState(1);
...

useEffect(() => {
    ...
    setTableKey(tableKey + 1);
}, [tableData]);

...
<DataTable
    key={tableKey}
    data={tableData}/>

리액트가 JSX 코드에서 부란을 인쇄하지 않는다는 사실을 이용하여 일반 후크를 사용하여 강제로 리렌더를 사용할 수 있습니다.

// create a hook
const [forceRerender, setForceRerender] = React.useState(true);

// ...put this line where you want to force a rerender
setForceRerender(!forceRerender);

// ...make sure that {forceRerender} is "visible" in your js code
// ({forceRerender} will not actually be visible since booleans are
// not printed, but updating its value will nonetheless force a
// rerender)
return (
  <div>{forceRerender}</div>
)

단일 라인 솔루션:

const useForceUpdate = () => useState()[1];

useState는 값의 쌍을 반환합니다.현재 상태와 이를 갱신하는 함수(상태세터). 여기서는 강제로 재렌더를 수행하기 위해 세터만 사용합니다.

react-tidy 커스텀 훅을 가지고 있습니다.useRefresh:

import React from 'react'
import {useRefresh} from 'react-tidy'

function App() {
  const refresh = useRefresh()
  return (
    <p>
      The time is {new Date()} <button onClick={refresh}>Refresh</button>
    </p>
  )
}

이 후크에 대해 자세히 알아보기

면책사항 저는 이 도서관의 작가입니다.

의 ★★★★★★★★★forceUpdate를 경유하지 않습니다.counter"CHANGE: "CHANGE: "CHANGE:

// Emulates `forceUpdate()`
const [unusedState, setUnusedState] = useState()
const forceUpdate = useCallback(() => setUnusedState({}), [])

★★★★★★★★★★★★★★★★★★{} !== {}★★★★★★ 。

한 줄의 솔루션:

const [,forceRender] = useReducer((s) => s+1, 0)

여기서 useReducer에 대해 배울 수 있습니다.https://reactjs.org/docs/hooks-reference.html#usereducer

이렇게 하면 컴포넌트에 따라 3회 렌더링됩니다(동일한 요소를 가진 배열은 동일하지 않습니다).

const [msg, setMsg] = useState([""])

setMsg(["test"])
setMsg(["test"])
setMsg(["test"])
const useForceRender = () => {
  const [, forceRender] = useReducer(x => !x, true)
  return forceRender
}

사용.

function Component () {
  const forceRender = useForceRender() 
  useEffect(() => {
    // ...
    forceRender()
  }, [])

컴포넌트에 를 하십시오.forceUpdateapi를 참조해 주세요.문서에서는 다음과 같이 언급하고 있습니다.

일반적으로 forceUpdate()의 모든 사용을 피하고 render() 내의 this.props 및 this.state에서만 읽어야 합니다.

다만, 문서에는 다음과 같은 것도 기재되어 있습니다.

render() 메서드가 다른 데이터에 의존하는 경우 forceUpdate()를 호출하여 컴포넌트를 재렌더링해야 함을 React에 알릴 수 있습니다.

때문에 사용 , 용, 용, 에, cases, cases, cases, cases, cases, cases, cases, cases, cases를 사용하지만forceUpdate희귀할 수도 있고 한번도 사용해 본 적은 없지만, 제가 작업한 일부 레거시 기업 프로젝트에서 다른 개발자가 사용하는 것을 본 적이 있습니다.

기능 컴포넌트의 동등한 기능에 대해서는, 이 URL 에 있는 「Respect Docs for HOOKs」를 참조해 주세요.위의 URL 에 따라, 「useReducer」후크를 사용하고, 다음의 URL 에 액세스 할 수 있습니다.forceUpdate츠미야

샘플 " " " " "that does not use state or props다음 URL에 있는 CodeSandbox에서도 구할 수 있습니다.

import React, { useReducer, useRef } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  // Use the useRef hook to store a mutable value inside a functional component for the counter
  let countref = useRef(0);

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

  function handleClick() {
    countref.current++;
    console.log("Count = ", countref.current);
    forceUpdate(); // If you comment this out, the date and count in the screen will not be updated
  }

  return (
    <div className="App">
      <h1> {new Date().toLocaleString()} </h1>
      <h2>You clicked {countref.current} times</h2>
      <button
        onClick={() => {
          handleClick();
        }}
      >
        ClickToUpdateDateAndCount
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

메모: useReducer 대신 useState 훅을 사용하는 대체 접근법도 이 URL에서 이용할 수 있습니다.

Hook에서 강제로 재렌더를 수행하는 방법은 여러 가지가 있습니다.

는 ★★★★★★★★★★의 간단한 방법useState()및및 、 체체체끝끝끝 。

const [, forceRender] = useState({});

// Anywhre
forceRender({});

Codesandbox

파티에는 조금 늦었지만 대부분의 답변이 forceUpdate 라이프 사이클 메서드에 콜백을 전달할 수 있는 부분을 놓치고 있는 것을 알 수 있습니다.

리액트 소스 코드에 따라 이 콜백은 setState 메서드의 콜백과 같은 동작을 합니다.이 동작은 업데이트 후에 실행됩니다.

따라서 가장 올바른 구현은 다음과 같습니다.

    /**
 * Increments the state which causes a rerender and executes a callback
 * @param {function} callback - callback to execute after state update
 * @returns {function}
 */
export const useForceUpdate = (callback) => {
    const [state, updater] = useReducer((x) => x + 1, 0);

    useEffect(() => {
        callback && callback();
    }, [state]);

    return useCallback(() => {
        updater();
    }, []);
};

어레이를 사용하여 작업하다가 이 문제를 발견했습니다. 명시적인 「」가 아니고, 「」가 됩니다.forceUpdate다음 코드를 사용하여 어레이를 분해하고 새로운 값을 설정하는 다른 방법을 찾았습니다.

    setRoutes(arr => [...arr, newRoute]); // add new elements to the array
    setRouteErrors(routeErrs => [...routeErrs]); // the array elements were changed

어레이의 카피라도 훅을 기동하지 않는 것이 매우 흥미로웠습니다.리액트가 얄팍한 비교를 하는 것 같은데

언급URL : https://stackoverflow.com/questions/53215285/how-can-i-force-a-component-to-re-render-with-hooks-in-react

반응형