응답에 useState 훅이 있는 콜백을 사용하는 방법
후크가 달린 기능성 컴포넌트를 사용하고 있습니다.자녀에서 부모 상태를 업데이트해야 합니다.Parent에서 prop 기능을 사용하고 있습니다.현재 상태가 아닌 이전 상태가 되는 것을 제외하고 모든 것이 정상적으로 작동합니다.useState 훅 설정 현재 상태를 설정하기 전에 프로펠러 기능이 실행됩니다.useState 콜 후에 콜백 기능이 실행되기를 어떻게 기다릴 수 있습니까?클래스 베이스의 컴포넌트에서 setState(state, callback)와 같은 것을 찾고 있습니다.
코드 스니펫은 다음과 같습니다.
function Parent() {
const [Name, setName] = useState("");
getChildChange = getChildChange.bind(this);
function getChildChange(value) {
setName(value);
}
return <div> {Name} :
<Child getChildChange={getChildChange} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
handleChange = handleChange.bind(this);
function handleChange(ele) {
setName(ele.target.value);
props.getChildChange(collectState());
}
function collectState() {
return Name;
}
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
useEffect/useLayoutEffect를 사용하면 다음과 같이 할 수 있습니다.
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
첫 번째 렌더링 시 콜백이 실행되지 않도록 하려면 이전 버전을 조정합니다.
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
const didMount = React.useRef(false);
React.useEffect(() => {
if (!didMount.current) {
didMount.current = true;
return;
}
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
여기 좀 더 자세히.
setState(updater, callback)
위해서useState
다음 구현은 클래스의 원래 콜백에 매우 가깝습니다.
- 초기 렌더링 시 콜백 실행이 생략됨 - 상태 업데이트 시 콜백 실행만 수행하려고 합니다.
- 콜백은, 각각에 대해서 다이나믹하게 할 수 있습니다.
setState
호출(클래스 등)
사용.
const App = () => {
const [state, setState] = useStateCallback(0); // same API as useState
const handleClick = () => {
setState(
prev => prev + 1,
// second argument is callback, `s` being the *updated* state
s => console.log("I am called after setState, state:", s)
);
};
return <button onClick={handleClick}>Increment</button>;
}
useStateCallback
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null); // init mutable ref container for callbacks
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb; // store current, passed callback in ref
setState(state);
}, []); // keep object reference stable, exactly like `useState`
useEffect(() => {
// cb.current is `null` on initial render,
// so we only invoke callback on state *updates*
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null; // reset callback after execution
}
}, [state]);
return [state, setStateCallback];
}
TypeScript version
function useStateCallback<T>(
initialState: T
): [T, (state: T, cb?: (state: T) => void) => void] {
const [state, setState] = useState(initialState);
const cbRef = useRef<((state: T) => void) | undefined>(undefined); // init mutable ref container for callbacks
const setStateCallback = useCallback((state: T, cb?: (state: T) => void) => {
cbRef.current = cb; // store current, passed callback in ref
setState(state);
}, []); // keep object reference stable, exactly like `useState`
useEffect(() => {
// cb.current is `undefined` on initial render,
// so we only invoke callback on state *updates*
if (cbRef.current) {
cbRef.current(state);
cbRef.current = undefined; // reset callback after execution
}
}, [state]);
return [state, setStateCallback];
}
상세 정보: Respect Hooks FAQ: 인스턴스 변수와 같은 것이 있습니까?
작업 예
const App = () => {
const [state, setState] = useStateCallback(0);
const handleClick = () =>
setState(
prev => prev + 1,
// important: use `s`, not the stale/old closure value `state`
s => console.log("I am called after setState, state:", s)
);
return (
<div>
<p>Hello Comp. State: {state} </p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null);
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb;
setState(state);
}, []);
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null;
}
}, [state]);
return [state, setStateCallback];
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<script>var { useReducer, useEffect, useState, useRef, useCallback } = React</script>
<div id="root"></div>
React 16.x 이후에서는 상태 변경 시 콜백 함수를 호출하는 경우useState
훅을 사용하면useEffect
상태 변경에 연결된 후크.
import React, { useEffect } from "react";
useEffect(() => {
props.getChildChange(name); // using camelCase for functions is recommended.
}, [name]); // this will call getChildChange on initial render and when ever name changes.
사실, 당신은 그것을 사용하는 것을 피해야 한다.this
리액트 훅 사용 시.그것은 부작용을 일으킨다.그래서 리액션 팀이react hooks
.
바인드를 시도하는 코드를 삭제한 경우this
그냥 지나가면 돼요.setName
의Parent
로.Child
그리고 그것을 불러들인다.handleChange
클리너 코드!
function Parent() {
const [Name, setName] = useState("");
return <div> {Name} :
<Child setName={setName} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
function handleChange(ele) {
setName(ele.target.value);
props.setName(ele.target.value);
}
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
게다가 2개의 복사본을 작성할 필요가 없습니다.Name
(1인치)Parent
그리고 다른 하나는Child
) '단일 진실의 원천' 원칙을 고수한다.Child
국가를 소유할 필요는 없다Name
하지만 그것을 받는 것은Parent
클리어러 노드!
function Parent() {
const [Name, setName] = useState("");
return <div> {Name} :
<Child setName={setName} Name={Name}></Child>
</div>
}
function Child(props) {
function handleChange(ele) {
props.setName(ele.target.value);
}
return (<div>
<input onChange={handleChange} value={props.Name}></input>
</div>);
}
상태가 변경되면 callBack 함수를 호출하는 커스터마이즈 함수를 작성할 수 있습니다.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useStateCallbackWrapper = (initilValue, callBack) => {
const [state, setState] = useState(initilValue);
useEffect(() => callBack(state), [state]);
return [state, setState];
};
const callBack = state => {
console.log("---------------", state);
};
function App() {
const [count, setCount] = useStateCallbackWrapper(0, callBack);
return (
<div className="App">
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
`
이를 실현하는 또 다른 방법:
const [Name, setName] = useState({val:"", callback: null});
React.useEffect(()=>{
console.log(Name)
const {callback} = Name;
callback && callback();
}, [Name]);
setName({val:'foo', callback: ()=>setName({val: 'then bar'})})
이를 위해서는 useCallback 훅을 사용할 수 있습니다.
function Parent() {
const [name, setName] = useState("");
const getChildChange = useCallback( (updatedName) => {
setName(updatedName);
}, []);
return <div> {name} :
<Child getChildChange={getChildChange} ></Child>
</div>
}
function Child(props) {
const [name, setName] = useState("");
function handleChange(ele) {
setName(ele.target.value);
props.getChildChange(ele.target.value);
}
function collectState() {
return name;
}
return (<div>
<input onChange={handleChange} value={name}></input>
</div>);
}
function Parent() {
const [Name, setName] = useState("");
getChildChange = getChildChange.bind(this);
function getChildChange(value) {
setName(value);
}
return <div> {Name} :
<Child getChildChange={getChildChange} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
handleChange = handleChange.bind(this);
collectState = collectState.bind(this);
function handleChange(ele) {
setName(ele.target.value);
}
function collectState() {
return Name;
}
useEffect(() => {
props.getChildChange(collectState());
});
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
useEffect
componentDidMount, componentDidUpdate로 동작하기 때문에 상태를 갱신하면 동작합니다.
언급URL : https://stackoverflow.com/questions/54954091/how-to-use-callback-with-usestate-hook-in-react
'programing' 카테고리의 다른 글
Visual Studio 2017 리액트 프로젝트 (0) | 2023.03.31 |
---|---|
사전 정의된 유형 'System'입니다.Object'가 정의되어 있지 않거나 .net 4.6을 Import하지 않았습니다. (0) | 2023.03.31 |
ASP 후 아약스에 항변형 토큰을 포함한다.넷 MVC (0) | 2023.03.31 |
플러그인의 wp_cron_event()가 cron 이벤트를 스케줄링하지 않음 (0) | 2023.03.31 |
jsx의 html 태그 자동 완성(하위 텍스트) (0) | 2023.03.31 |