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:useState
useReducer
복잡함을 줄이기 위해 환원제를 사용합니다.
메모: 기준 불안정성
「」를 사용합니다..bind
useState
이치
에 넣을 수도 있어요.useCallback
여기 이 답변에서 이미 설명했듯이, 섹시한 원라이너™는 아닐 것입니다.Reducer 버전은 이미 렌더링 간의 참조 평등(안정성)을 유지하고 있습니다.이것은 소품 내의 forceUpdate 함수를 다른 컴포넌트에 전달하는 경우에 중요합니다.
플레인 JS
const forceUpdate = React.useState({})[1].bind(null, {}) // see NOTE above
const forceUpdate = React.useReducer(() => ({}))[1]
다른 사람들이 언급했듯이useState
mobx-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()
}, [])
컴포넌트에 를 하십시오.forceUpdate
api를 참조해 주세요.문서에서는 다음과 같이 언급하고 있습니다.
일반적으로 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({});
파티에는 조금 늦었지만 대부분의 답변이 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
'programing' 카테고리의 다른 글
JSON 또는 SOAP(XML)? (0) | 2023.02.16 |
---|---|
웹 사이트에서 악성 코드/멀웨어를 찾는 방법 (0) | 2023.02.16 |
React Native 앱이 닫혔을 때(일시 중단되지 않았을 때) 어떻게 감지합니까? (0) | 2023.02.16 |
VS 코드에서 "Comments is not allowed in JSON" 오류를 비활성화합니다. (0) | 2023.02.16 |
현재 Angular와 호환되는 부트스트랩 3JS 부트스트랩 지시사항? (0) | 2023.02.16 |