μλ νμΈμ, μ΅κ·Ό React Hookμ μ°κ΅¬νκ³ μμ΅λλ€. νλ₯ν©λλ€.
νμ§λ§ λ¬Έμ κ° μμ΅λλ€. React Hook μ€λͺ μμ Googleμμ λ΄ λ¬Έμ λ₯Ό ν΄κ²°ν μ μ ν λ΅λ³μ μ°Ύμ§ λͺ»νμ΅λλ€.
useEffectμ ν¨μμ ν¨μ κ΅¬μ± μμλ₯Ό ν¨κ» μ¬μ©νμ λ μλμ κ°μ΄ useEffectμ μ’ μμ±μ μ§μ νμ§ μμλ€λ κ²½κ³ κ° λ°μνμ΅λλ€.
λ΄ λ¬Έμ λ₯Ό ν΄κ²°ν λ°©λ²μ΄ μμ΅λκΉ? λλ μ€λ«λμ κ·Έκ²μ λν΄ μκ°ν΄ μλ€.
νμ¬ νλμ 무μμ λκΉ?
React Hook useEffect has a missing dependency: 'setCenterPosition'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)
μ½λμλλ°μ€μ λ―Έλ μ¬ν:
https://codesandbox.io/s/trusting-kowalevski-oet4b
μ΄λ€ μ루μ μ΄λ κ°μ¬ν©λλ€.
μνΈ
function App() {
const [elePositionArr, setElePositionArr] = useState([
{ left: 0, top: 0 },
{ left: 0, top: 0 },
{ left: 0, top: 0 }
]);
const stageRef = useRef(null);
const Stage = useRef({ w: 0, h: 0 });
const currentIndex = useRef(0);
useEffect(() => {
// Record the size of the stage
const stageW = stageRef.current.scrollWidth;
const stageH = stageRef.current.scrollHeight;
Stage.current = { w: stageW, h: stageH };
const index = Math.floor(Math.random() * 3);
currentIndex.current = index;
setCenterPosition(index);
}, []);
// Centering a block element
function setCenterPosition(index) {
let cacheEle = elePositionArr;
// calc center postion
const centerOfLeft = Stage.current.w / 2 - 25;
const centerOfTop = Stage.current.h / 2 - 25;
cacheEle = cacheEle.map((item, i) => {
const randomWNum = Math.floor(Math.random() * Stage.current.w) - 50;
const randomHNum = Math.floor(Math.random() * Stage.current.h) - 50;
const randomLeft = randomWNum <= 50 ? 50 : randomWNum;
const randomTop = randomHNum <= 50 ? 50 : randomHNum;
let newItem;
if (index === i) {
newItem = { left: centerOfLeft, top: centerOfTop };
} else {
newItem = { left: randomLeft, top: randomTop };
}
return newItem;
});
setElePositionArr(cacheEle);
}
function handleClickLi(index) {
if (currentIndex.current !== index) {
setCenterPosition(index);
currentIndex.current = index;
}
}
return (
<div className="container">
<div className="stage" ref={stageRef}>
{elePositionArr.map((item, index) => (
<div className="ele" key={index} style={item}>
{index}
</div>
))}
</div>
<ul className="nav">
{elePositionArr.map((item, index) => (
<li
className={currentIndex.current === index ? "active-li" : ""}
onClick={() => {
handleClickLi(index);
}}
key={"li" + index}
>
{index}
</li>
))}
</ul>
</div>
);
}
λ€μ μ§λ¬Έμ λ΅ν΄μΌ ν©λλ€.
https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies
λ€μ μ§λ¬Έμ λ΅ν΄μΌ ν©λλ€.
https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies
@gaearon
λ΄ λ¬Έμ λ₯Ό ν΄κ²°νμ§ λͺ»νμ΅λλ€. λ΄ λ¬Έμ κ° λ νΉλ³ν©λλ€. λ΄ μ€ν functionsetElePositionArrμ΄ componentDidMount λ° handleClickμμ μ€νλκΈ°λ₯Ό μνμ§λ§ React Hook κΈ°λ₯μ΄ λ΄ μꡬ μ¬νμ μΆ©μ‘±νμ§ μκ³ κ²½κ³ κ° λνλ©λλ€.
λ΄ μ§λ¬Έμ : React Hookμ useEffectμ ν¨μμ setState μμ μ λν ν¨μ κ΅¬μ± μμλ₯Ό νΈμΆν μ μμ΅λκΉ?
λ λ²μ§Έ μ§λ¬Έμ λ΅ν μ μλλ‘ μ΄μ΄ λ‘λλ€.
λμΌν ESLint κ²½κ³ κ° νμλμ§λ§ μ κ²½μ°μλ κ΅¬μ± μμκ° λ§μ΄νΈλ λ λΉλκΈ° νΈμΆμ νκ³ μΆμ΅λλ€.
const ManageTagsModalBody: React.FC<IProps> = ({ children, getTags }) => {
useEffect(() => {
getTags();
}, []);
return <div>{children}</div>;
};
Line 12: React Hook useEffect has a missing dependency: 'getTags'. Either include it or remove the dependency array. If 'getTags' changes too often, find the parent component that defines it and wrap that definition in useCallback react-hooks/exhaustive-deps
ManageTagsModalBody
λ λ°μ΄ν°μ μμ‘΄νμ§ μμΌλ©° κ΅¬μ± μμκ° λ λλ§λ λλ§λ€ λ°μ΄ν°λ₯Ό λ‘λνλ λνΌλ‘λ§ μ¬μ©λ©λλ€. children
κ΅¬μ± μμκ° getTags
κ° κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μ¬μ©νκ³ μλ€λ μ μ μ£Όλͺ©ν κ°μΉκ° μμ΅λλ€.
μ’ μμ± λͺ©λ‘μ 무μμ μΆκ°ν΄μΌ ν μ§ μ λͺ¨λ₯΄κ² μ΅λλ€.
μ€λͺ
λ κΆκΈν©λλ€.
React Hook useEffectμ λλ½λ μ’
μμ±: 'dispatch'κ° μμ΅λλ€.
useEffect(() => {
axios.get('http://localhost:8000/api/future-registrations')
.then((result) => {
dispatch(initRegistrationsAction(result.data));
});
}, []);
λμΌν λ¬Έμ κ° μ¬κΈ°μ μμ΅λλ€. μ΄μν κ·μΉ.
μ¬κΈ°λ λ§μ°¬κ°μ§μ λλ€. https://github.com/facebook/react/issues/15865#issuecomment -506503377μμμ κ°μ΄ κ°λ¨ν©λλ€.
useEffect(() => {
dispatch(fetchPosts());
}, []);
μ΄ κ²½κ³ λ₯Ό μ΅μ νλ λ°©λ²μ΄ μμ΅λκΉ?
κ²½κ³ λ©μμ§μμ μ μν λλ‘ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
const initFetch = useCallback(() => {
dispatch(fetchPosts());
}, [dispatch]);
useEffect(() => {
initFetch();
}, [initFetch]);
@fayway κ·Έλ¬λ©΄ initFetch λ° dispatch κ°μ΄ λ³κ²½λ λλ§λ€ useEffectμ μ½λ°±μ΄ μ€νλ©λλ€.
κ·Έλ ν λ² μ½λ°±μ μ€ννκ³ μΆμ΄
@shkyung μ κ²½μ° initFetch λ μμΈ(μ μ₯μ)μ λ³κ²½νμ§ μμ΅λλ€. ν견λ λ³κ²½λμ§ μμ΅λλ€.
μ΄μ©λ©΄ μ΄λ κ² λ μ μμ΅λλ€
const setCenterPosition = useRef(null)
setCenterPosition.current = useCallback( ()=>{} ,[deps])
effect(()=>{ setCenterPosition.current() },[setCenterPosition,otherDeps])
μ΄ λ³νλ λ€μ μ°μ€κ½μ€λ½κ³ μμ§ν λ§ν΄μ μν¨κ³Όλ₯Ό λ³λ κ²μ²λΌ 보μ λλ€. μ€νλ € μ΄μ λ²μ μΌλ‘ λ‘€λ°±νκ³ μ΄ λ¬Έμ μ λν΄ μκ°νκ² νμμμ€.
κ°μ λ¬Έμ κ° μμ΅λλ€. componentDidMountμμλ§ λ΄ κ°μ Έμ€κΈ°κ° μ€νλκΈ°λ₯Ό μν©λλ€. λ°°μ΄μ μ’ μμ±μ μΆκ°νλ©΄ λμ μ λ°λ³΅μ μΌλ‘ λλ¬νκ² λ©λλ€.
React Hook useEffectμ λλ½λ μ’ μμ±: 'dispatch'κ° μμ΅λλ€.
const [state, dispatch] = useReducer(reducer, initialState);
const { count, step } = state;
useEffect(() => {
const id = setInterval(() => {
dispatch({ type: 'tick' }); // Instead of setCount(c => c + step);
}, 1000);
return () => clearInterval(id);
}, [dispatch]);
μ΄κ²μ λ§€μ° μΌλ°μ μΈ μ¬μ© μ¬λ‘μΈ κ² κ°μ΅λλ€. νμ¬ νλ‘μ νΈμμ κ²ͺμλ κ²μ λλ€.
ν¨κ³Ό νν¬λ₯Ό ν λ²λ§ μ€ννκ³ μΆμ§λ§ μμ μ μνμλ§ κ΄μ¬μ΄ μμ§λ§ μ’
μμ±μ΄ μμ΅λλ€. νμ¬ μ¬μ© μ€
// eslint-disable-next-line react-hooks/exhaustive-deps
,
Linting κ·μΉμ λλ €λ©΄ μ΄ κ²½μ°μλ λμ§ μμλ λ©λλ€.
μ΄κ²μ λ§€μ° μΌλ°μ μΈ μ¬μ© μ¬λ‘μΈ κ² κ°μ΅λλ€. νμ¬ νλ‘μ νΈμμ κ²ͺμλ κ²μ λλ€.
ν¨κ³Ό νν¬λ₯Ό ν λ²λ§ μ€ννκ³ μΆμ§λ§ μμ μ μνμλ§ κ΄μ¬μ΄ μμ§λ§ μ’ μμ±μ΄ μμ΅λλ€. νμ¬ μ¬μ© μ€
// eslint-disable-next-line react-hooks/exhaustive-deps
,
Linting κ·μΉμ λλ €λ©΄ μ΄ κ²½μ°μλ λμ§ μμλ λ©λλ€.
Lintλ₯Ό λ«λ κ²μ μμ ν΄κ²°μ± μΌ λΏμ΄λ©° μ΄ λ¬Έμ μ ν΅μ¬μ νν¬λ₯Ό μ΄ν΄νλ λ° μΆ©λΆνμ§ μμ΅λλ€.
λμΌν λ¬Έμ κ° μ¬κΈ°μ μμ΅λλ€. useEffect() λ΄λΆμμ ν¨μλ₯Ό ν λ² μ€ννκ³ μΆμμ΅λλ€. λ λ²μ§Έ 맀κ°λ³μλ‘ []λ₯Ό μ¬μ©νλ©΄ μνλ λλ‘ μνλμ§λ§ κ³μ μ΄ κ²½κ³ κ° νμλ©λλ€.
μ€λκΉμ§ μ νλ‘μ νΈμμ λ³Έ μ μ΄ μκΈ° λλ¬Έμ μ΄μν κ²½κ³ μ λλ€. κ΅¬μ± μμκ° λ§μ΄νΈλμμ λ ν λ²λ§ νΈμΆλλ μ¬μ© μ¬λ‘λ₯Ό λ§μΉ©λλ€. 보νΈλΌκΈ° κ²½κ³ λ₯Ό 무μνλ κ² μΈμλ ν΄κ²° λ°©λ²μ΄ μλ κ² κ°μ΅λλ€.
μ¬κΈ°μ λ΄ 2μΌνΈλ₯Ό λ£κ³ μΆμ΅λλ€. νΉν Axiosλ₯Ό μ¬μ©νμ¬ λ€νΈμν¬ μμ²μ μ·¨μνλ κ²½μ°. νμν κ²½μ° λ³λμ λ¬Έμ λ₯Ό λ§λ€μ§λ§ μ΄ λ¬Έμ κ° λ μμ μκ² μ§μ μ μΈ μν₯μ λ―Έμ³€λ€κ³ λκΌμ΅λλ€. κ·Έλμ λ΄ useApi νν¬λ λ€μκ³Ό κ°μ΅λλ€ -
import axios, { AxiosInstance } from "axios";
import axiosRetry from "axios-retry";
import { FetchEnv } from "../../utilities";
import { useStorage } from "../useStorage";
export const useApi = ({ isAuth = false, retries = 3 } = {}) => {
const cancelToken = axios.CancelToken.source();
const { getItem } = useStorage();
const getBaseUrl = () => {
return FetchEnv({
defaultValue: "http://api.example.com",
key: "API_URI"
});
};
const authorizedClient = (client: AxiosInstance) => {
const session = getItem("SESSION", "sessionStorage");
const hasAccessToken = Boolean(session.tokens.accessToken);
if (isAuth && !hasAccessToken) {
console.error("No access token found to initiate authorized request.");
return client;
} else {
client.defaults.headers[
"Authorization"
] = `Bearer ${session.tokens.accessToken}`;
return client;
}
};
const buildFetch = (): AxiosInstance => {
const client = axios.create({
baseURL: getBaseUrl(),
cancelToken: cancelToken.token
});
axiosRetry(client, { retries });
return isAuth ? authorizedClient(client) : client;
};
return {
cancelRequest: cancelToken.cancel,
fetch: buildFetch()
};
};
κ΅¬μ± μμ λ΄μμ μ΄ νν¬λ₯Ό μ¬μ©νλ €λ©΄ λ€μκ³Ό κ°μ΄ μ μνλ©΄ λ©λλ€. κ·Έλ¬λ©΄ λ§μ΄νΈ μ, useEffect λ΄μμ, μ΄λ²€νΈ νΈλ€λ¬μ μΌλΆλ‘ μΈμ¦λ νΈμΆκ³Ό μΈμ¦λμ§ μμ νΈμΆμ λͺ¨λ μννλ λ° μ¬μ©ν μ μμ΅λλ€. cancelRequestλ μμ±λ κ³ μ μ·¨μ ν ν°μ λλ€. μ΄ κ΅¬μ± μμμ κ΄λ ¨λ "fetch" axios μΈμ€ν΄μ€μ μμ μ΄λ£Ήλλ€.
const { cancelRequest, fetch } = useApi();
μ΄λ€ μ΄μ λ‘λ μ΄ κ΅¬μ± μμκ° λ§μ΄νΈ ν΄μ λλ©΄ λ€μμ΄ νΈμΆλ©λλ€.
useEffect(() => {
return () => {
cancelRequest("Auth network request cancelled");
};
}, []);
μ΄μ νμ¬ μλ²½νκ² μλν©λλ€. κ·Έλ¬λ κ²½κ³ κ° μ μ©λλ©΄(cancelRequestλ₯Ό useEffect μ’ μμ±μΌλ‘ μ€μ ) fetch λ©μλκ° νΈμΆλ λ λ€νΈμν¬ μμ²μ μ¦μ μ·¨μν©λλ€. μ‘°μΈμ μ£Όμλ©΄ λλ¨ν κ°μ¬νκ² μ΅λλ€. κ·Έλ¬λ νμ¬λ‘μλ ts-lintκ° μ΄λ₯Ό λΉνμ±ννλ κ²μ΄ μ μΌν ν΄κ²°μ± μΈ κ² κ°μ΅λλ€...
λλ μ¬κΈ°μ λ¬Έμ κ° μ°λ¦¬κ° νν¬μ λν΄ μκ°νλ λ°©μ μΌ μ μλ€κ³ μκ°ν©λλ€. @luojinghui μ μ견 μ λμ 보μ΄λ κ²λ³΄λ€ λ λ§μ κ²μ΄ μμμ μμ¬ν©λλ€. μ°λ¦¬λ λ€λ₯΄κ² μκ°ν΄μΌ νμ§ μμκΉμ? μΌλΆ 리ν©ν λ§μΌλ‘ νν¬ μ€ νλμμ μ΄ λ¬Έμ λ₯Ό μ κ±°ν μ μμμ΅λλ€. κ²°κ³Όμ μΌλ‘ μ½λκ° λ λͺ νν΄μ§λλ€.
λ°λ‘ μμ @Stoner609 μ μ μμ νμ΄λ° μ½λκ° useCallback νν¬μ μμ΄μΌ νλμ§ κΆκΈνμ΅λλ€. κ·Έλλ μ’ μμ±μΌλ‘ κΈ°λ₯(μ μ μ΄μ΄μΌ ν¨)μ κ°λ κ²μ μ¬μ ν ββμ΄μν©λλ€.
μ΄ κ²½μ°λ μΌμ’ μ μμΈκ° λμ΄μΌ νλ€κ³ μκ°ν©λλ€
κ΅¬μ± μμκ° λ‘λλκ³ λ§€κ° λ³μλ₯Ό λ°λ ν¨μλ₯Ό ν λ²λ§ μ€ννλ €λ κ²½μ° useRefλ₯Ό μ¬μ©νμ¬ κ²½κ³ λ₯Ό νΌν μ μμ΅λλ€. λ€μκ³Ό κ°μ΄ μλν©λλ€.
const InitialPropA= useRef(propA);
useEffect(() => {
myFunction(InitialPropA.current);
}, [myFunction, InitialPropA]);
κ²½κ³ λ©μμ§μμ μ μν λλ‘ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
const initFetch = useCallback(() => { dispatch(fetchPosts()); }, [dispatch]); useEffect(() => { initFetch(); }, [initFetch]);
λ΄κ° μ΄ μ¬μΉ μλ λλ΅μ μ’μνλ λ§νΌ μ΄κ²μ μΌλ°μ μΌλ‘ λ΄ μ½λμμ μΌμ΄λλ μΌμ
λλ€.
λμ€ν¨μΉκ° μ¬λΌμ§λ€λ μ±κ°μ κ²½κ³ λ₯Ό λ°κ³ μΆμ§ μμ΅λλ€.
λλ κ·Έ λ―Έμ€ν°λ¦¬μ λ°°μ΄μμ λ¬΄μ¨ μΌμ΄ μ μΌμ΄λλμ§ μ νν μκ³ μΆμ΅λλ€. :)
κ²½κ³ λ©μμ§μμ μ μν λλ‘ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
const initFetch = useCallback(() => { dispatch(fetchPosts()); }, [dispatch]); useEffect(() => { initFetch(); }, [initFetch]);
μ΄κ²μ λν APIμ κ°μ κ²½μ°μ λ©λͺ¨λ¦¬ λμλ₯Ό μμ±ν μ μμΌλ©°, 무ν 루νμμ νΈμΆμ λ§λ€ κ²μ λλ€.
μ λ§ μ΄κ²μ λν μμ μ΄ νμν©λλ€. useEffect()
λ΄λΆμ ν¨μλ₯Ό ν λ²λ§ μ€ννλ €λ κ²½μ° κ³μ μ€λ₯κ° λ°μνκ³ ν΄κ²° λ°©λ²μ λν μμ΄λμ΄κ° μμ΅λλ€.
κ°μ μ€λ₯μ μ§λ©΄ -
React Hook useEffectμ 'props' μ’ μμ±μ΄ λλ½λμμ΅λλ€. κ·Έλ¬λ, "μν"λ°λμ§ν μμ μ΄ useEffect μ½μ "μν"μ€λΈμ νΈ μΈλΆ destructure λ° useEffect λ΄λΆ κ·Έ νΉμ μνμ μ°Έμ‘°νλ―λ‘ μ΄λ€ μν λ³κ²½, λ°μ - νν¬ λ λ / μ μ depsμ λ°κΏ
μ½λ -
useEffect(() => {
props.dispatch(searchMediaAction("rain"));
}, []);
@luojinghui : 보νΈλΌκΈ° μ€λ₯λ₯Ό ν΄κ²°νλ€λ©΄ μλ €μ£ΌμΈμ
κ°μ μ€λ₯
κ°μ λ¬Έμ . componentDidMountμ λμμ λͺ¨λ°©νκ³ μΆμ΅λλ€. λλ κ²½κ³ μ κ΄μ¬μ΄ μμ΅λλ€. λ³κ²½ μ¬νμ΄ μμ λ νν¬λ₯Ό λ€μ μ€ννκ³ μΆμ§ μμ΅λλ€.
useEffect()
λν λ λ²μ§Έ μΈμκ° []
μΈ κ²½μ° μ΄ κ²½κ³ λ₯Ό νμ νμ§ μμ κ²μ μ μν©λλ€. μ΄ κ²½μ° b/c κ°λ°μλ μ΄ ν¨κ³Όκ° ν λ²λ§ μ€νλκ³ λ°λΌμ μ¬μ©νκΈ°λ₯Ό _μν©λλ€_ μ΄κΈ° prop κ°μ΄λ©° νμ λ λλ§μμ propμ΄ λ³κ²½λλμ§ μ¬λΆλ μ κ²½ μ°μ§ μμ΅λλ€.
μ¬λ‘ 1:
μ΄κΈ°ν μμ μ§μ λ 맀κ°λ³μ κ°μ΄ λ³κ²½λ λ(lint κ²½κ³ μμ μ μ μλ―μ΄) ν¨μλ₯Ό μ€ννλ €λ©΄ ν΄λΉ 맀κ°λ³μλ₯Ό λ°°μ΄μ μ λ¬ν©λλ€.
μ¬λ‘ 2:
ν¨μκ° μ΄κΈ°ν μ μ νν ν λ² μ€νλλλ‘ νλ €λ©΄ λΉ λ°°μ΄μ μ¬μ©νμ¬ ν¨κ³Όκ° ν λ²λ§ νΈλ¦¬κ±°λλλ‘ ν©λλ€.
Case 2μμλ κΈ°λ³Έμ μΌλ‘ React Hook λ¬Έμ μ¬μμ λ°λΌ componentDidMount μ΄λ²€νΈλ₯Ό μμ ν©λλ€. Lint μ€λ₯λ React Hook λ¬Έμ λ° κ°λ°μ κΈ°λμΉμ μΌμΉνμ§ μμ΅λλ€.
μ΄κ² μ λ«νμλμ?
μ΄λ€ ν΄κ²°μ± μ΄ μμ΅λκΉ?
@kennylbj
λ€μν μ μμ μλν ν μ΄κ²μ΄ κΆκ·Ήμ μΌλ‘ μ μκ² ν¨κ³Όμ μ΄μμ΅λλ€. λλ eslint-disableμ μ¬μ©νμ§ μλ κ²μ μ νΈνμ§λ§ μ΄λ³΄μμκ²λ μ½λλ₯Ό λΉκ΅μ κ°λ¨νκ² μ μ§νλ €κ³ νμ΅λλ€. μ΄ μ κ·Ό λ°©μμ μ¬μ©νλ©΄ useCallback λ΄λΆμμ νΈμΆνμ§ μκ³ λμ€ν¨μΉ ν¨μλ₯Ό μ λ¬ν μ μμ΅λλ€. λμμ΄ λμκΈ°λ₯Ό λ°λλλ€.
```μλ°μ€ν¬λ¦½νΈ
// ... ν¨μ μ»΄ν¬λνΈ λ΄λΆ
const { dispatchFunc } = 컀μ€ν
ν
();
const memoizeDispatchFunc = useCallback(dispatchFunc, []);
useEffect(() => {
λ©λͺ¨νλμ€ν¨μΉνν¬();
}, [memoizeDispatchFunc]);
````
λΉ λ°°μ΄μ μ κ±°ν μ μμ΅λκΉ? κ·Έλ κ² νλ©΄ μλνλ κ² κ°μ§λ§(μ½λλ μ¬μ ν μμλλ‘ μ€νλκ³ κ²½κ³ λ μ¬λΌμ§) κ·Έλ κ² ν΄μλ μ λλ μ΄μ κ° μλμ§ λͺ¨λ₯΄κ² μ΅λλ€.
useEffect(()=>{
myFunc();
}
)
@robthedev νλ₯ν μ루μ
.
reduxλ₯Ό μ¬μ©νλ©΄ μ½λλ₯Ό λ¨μνν μλ μμ΅λλ€.
const dispatch = useDispatch();
// redux can guarantee that the dispatch function will not change between renders.
// so we don't need to wrap it with useCallback for now.
useEffect(() => {
dispatch(actions());
}, [dispatch]);
Danμ μ΄ κΈ°μ¬λ μ μκ² λ§μ λμ
μ΄ λ¬Έμ μ λν ν΄κ²°μ± μ μ’ μμ±μ μ κ±°νλ κ²μ΄ μλλΌ κ΅¬μ± μμ μΈλΆμμ props λλ stateκ° νμνμ§ μμ ν¨μλ₯Ό νΈμ΄μ€νΈνκ±°λ μ μλ useCallbackμΌλ‘ λννλ κ²μ λλ€.
@kennylbj
λ€μν μ μμ μλν ν μ΄κ²μ΄ κΆκ·Ήμ μΌλ‘ μ μκ² ν¨κ³Όμ μ΄μμ΅λλ€. λλ eslint-disableμ μ¬μ©νμ§ μλ κ²μ μ νΈνμ§λ§ μ΄λ³΄μμκ²λ μ½λλ₯Ό λΉκ΅μ κ°λ¨νκ² μ μ§νλ €κ³ νμ΅λλ€. μ΄ μ κ·Ό λ°©μμ μ¬μ©νλ©΄ useCallback λ΄λΆμμ νΈμΆνμ§ μκ³ λμ€ν¨μΉ ν¨μλ₯Ό μ λ¬ν μ μμ΅λλ€. λμμ΄ λμκΈ°λ₯Ό λ°λλλ€.
// ... inside function component const { dispatchFunc } = customHook(); const memoizeDispatchFunc = useCallback(dispatchFunc, []); useEffect(() => { memoizeDispatchFunc(); }, [memoizeDispatchFunc]);
λμ ν¨κ» μμ μλ μλνμ§ μμ΅λλ€.
λ€μ μ€λ₯κ° λ°μν©λλ€.
TypeError: Cannot destructure property 'dispatchFunc' of 'componentDidMount(...)' as it is undefined.
@react-team: ν볡ν μμ©κ΅¬ μ½λ. :) κ·Έκ²μ λ Όλ¦¬μ μ΄κ³ λ€μ μ½μ μ μμ΅λκΉ... μ΄λ²€νΈλ μ¬μ©νκΈ° κ°λ¨ν΄μΌ ν©λλ€... λ¨μ§ ν¨μλ₯Ό νΈμΆνκΈ° μν΄ 5μ€ μ΄μμ λ Όλ¦¬λ₯Ό μμ±ν νμκ° μμ΅λλ€.
λλ₯Ό μν΄ λ€μκ³Ό κ°μ μν©μμ μ€λ₯κ° λνλ¬μ΅λλ€.
useEffect(() => {
props.getTasks()
}, [])
λλ μ΄κ²μ λ€μκ³Ό κ°μ΄ μμ νλ€.
const { getTasks } = props
useEffect(() => {
getTasks()
}, [getTasks])
μμ² λͺ
μ κ°λ°μκ° λμΌν λ¬Έμ μ μ§λ©΄νκ³ React κ°λ° νμ΄ μ€λ λλ₯Ό λ«κ³ λͺ¨λ μ¬λμ 무μν λ:
λ΄ λ¬Έμ λ μ΄ μ€λ λμ λ€λ₯Έ λ¬Έμ μ λ€λ₯΄κΈ° λλ¬Έμ λ€λ₯Έ λΆμν μνΌμ΄ ν λΌ κ΅¬λ©μ λΉ μ§ κ²½μ°λ₯Ό λλΉνμ¬ κ³΅μ νκ² μ΅λλ€.
function hydrate( _state, _errors=false) {
console.log('hydrate()');
setState({...state,..._state});
if(_errors){
setErrors({...errors,..._errors});
}
}
μ¬μ©μλ λ€μκ³Ό κ°μ΄ μνλ₯Ό μννκΈ° μν΄ useEffect()
μ ν¨κ» μ΄κ²μ μ¬μ©ν΄μΌ ν©λλ€.
useEffect(()=>{
hydrate({
name:'Garrett',
email:'[email protected]',
newsletter: 'yes'
});
},[hydrate]); //unfortunately, this causes an infinite render, because hydrate will always change
κ·Έλμ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ΄ μνλ¬Ό ν¨μλ₯Ό useCallback()
λννλλ‘ λ³κ²½νμ΅λλ€. μ΄μ λͺ¨λ λ λλ§λ€ λ³κ²½λμ§ μμΌλ©°(λ΄ μκ°μ) μ΄κ²μ΄ μ±λ₯μ λ μ’μ κ²μ
λλ€. λ΄ μ¬μ©μ μ§μ νν¬μμ λ°νλ λͺ¨λ λμ°λ―Έ ν¨μμ λν΄ μ΄κ²μ ꡬνν©λλ€.
const hydrate = useCallback(( _state, _errors=false )=> {
console.log('hydrate()');
setState({...state,..._state});
if(_errors){
setErrors({...errors,..._errors});
}
},[]);
λκ° μ΄κ²μ΄ μ¬μ€μΈμ§ νμΈν μ μμ΅λκΉ? useCallback
λ λ λλ§μμ hydrate
κ° λ³κ²½λλ κ²μ λ°©μ§νλ―λ‘ λ λμ μ±λ₯μ μν΄ μ΄λ¬ν λͺ¨λ κΈ°λ₯μ useCallback
μ λννλ κ²μ΄ μ’μ΅λλ€. ?
redux can guarantee that the dispatch function will not change between renders.
λΉμ μ κ·Έκ²μ λν΄ νμ ν©λκΉ?
κ·Έλ κ² λ§νλ λ¬Έμμ λ§ν¬νμμμ€.
μμΈν λ΄μ©μ https://overreacted.io/a-complete-guide-to-useeffect/#decoupling -updates-from-actionsλ₯Ό νμΈνκ±°λ ꡬν μΈλΆ μ¬νμ useEffect μμ€ μ½λ λ₯Ό νμΈν μ μμ΅λλ€.
μ¬κΈ°μμ Danμ΄ λ§ν κ²μ μ°Έμ‘°ν©λλ€.
λλ΅μ Reactκ° λμ€ν¨μΉ ν¨μκ° κ΅¬μ± μμ μλͺ λ΄λ΄ μΌμ νλλ‘ λ³΄μ₯νλ€λ κ²μ λλ€. λ°λΌμ μμ μμμλ κ°κ²©μ λ€μ ꡬλ ν νμκ° μμ΅λλ€.
λμ€ν¨μΉ ν¨μκ° μΌμ νλλ‘ λ³΄μ₯
μΏ¨, κ³ λ§μ!
μμ² λͺ μ κ°λ°μκ° λμΌν λ¬Έμ μ μ§λ©΄νκ³ React κ°λ° νμ΄ μ€λ λλ₯Ό λ«κ³ λͺ¨λ μ¬λμ 무μν λ:
κ±°μ μ΄κ²μ λλ€. μ¬κΈ°μμ νν¬λ₯Ό μλνκ³ μμΌλ©° 곡μ λ¬Έμμμ λ€λ£¨μ§ μκ³ μλ―Έκ° μλ κ²½κ³ λ₯Ό λ°μμ΅λλ€. "μ΄ ν¨κ³Όλ₯Ό ν λ²λ§ μ€ννμμμ€"μ κ°μ κΈ°λ³Έ μ¬μ© μ¬λ‘κ° μ΄λ κ² λ§μ λ¬Έμ λ₯Ό μΌμΌν€λ©΄ νν¬κ° μ§μ§ν μμ μ μνν μ€λΉκ° λμλμ§ μ λ§ κΆκΈν©λλ€.
κΈμ, μ€λ λκ° λ«ν μλ€λ μ¬μ€μ μ μΈνκ³ λ κ·Έλ€μ§ λ§ν κ²λ μμ΅λλ€.
κ°μ λ¬Έμ μ μ§λ©΄ν΄ μμ΅λλ€!
ν΄κ²°μ±
,
(κ·Έκ²μ λλ₯Ό μν΄ μΌνμ΅λλ€):
const onInit = function(){
console.log('initiated', Date.now());
}
useEffect(onInit, []);
λ¦°νΈ μͺ½μμ λ¬Έμ κ° ν΄κ²°λμμΌλ©΄ μ’κ² μ§λ§ μ΄λ΄...
@ra30r μ’μ ν΄κ²° λ°©λ²μ΄μ§λ§ λΆμμ©μ μΌμΌν¬ μ μλμ§ κΆκΈνμλκΉ? :μκ°:
μ¬μ ν μ무κ²λ? π
Udemyμ κ³Όμ μμ μμ μ ν¨μ± κ²μ¬ μ€λ₯λ₯Ό μ λ°νλ λ°©λ²μ λ°°μ΄ κ²½μ°κ° μμμ΅λλ€.
μ΄κ²μ λλ½λ μ’ μμ± "λμ€ν¨μΉ"λ₯Ό νΈλ¦¬κ±°νμ§λ§ μ¬μ ν μλνμ΅λλ€.
useEffect(() => {
if (state.business_name.value) {
const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
return () => clearTimeout(delay)
}
}, [state.business_name.value])
@ra30r μ μμ λ₯Ό μ¬μ©νμ¬ μ€λ₯λ₯Ό μ§μ°κΈ° μν΄ λ€μκ³Ό κ°μ΄ λ³κ²½νμ΅λλ€.
const businessNameAfterDelay = function () {
if (state.business_name.value) {
const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
return () => clearTimeout(delay)
}
}
useEffect(businessNameAfterDelay, [state.business_name.value])
μ΄κ² μ λ«νμλμ?
λλ λλ΅μ΄ μ΄λκ°μ μ£Όμ΄μ‘λ€κ³ λ―Ώμ΅λλ€. lol.. μ΄μ¨λ .. ν΄κ²°μ±
μ λ€μκ³Ό κ°μ΄ νλ κ²μ
λλ€:
useEffect(() => {
dispatch();
}, [dispatch]);
λμμ΄ λμκΈ°λ₯Ό λ°λλλ€!!
μ΄κ² μ λ«νμλμ?
λλ λλ΅μ΄ μ΄λκ°μ μ£Όμ΄μ‘λ€κ³ λ―Ώμ΅λλ€. lol.. μ΄μ¨λ .. ν΄κ²°μ± μ λ€μκ³Ό κ°μ΄ νλ κ²μ λλ€:
useEffect(() => { dispatch(); }, [dispatch]);
λμμ΄ λμκΈ°λ₯Ό λ°λλλ€!!
μ, κ·Έ ν΄κ²° λ°©λ²μ΄ μλν©λλ€. @kennylbj λ μΌλ§ μ μ μ¬κΈ°μμ λ§νμ΅λλ€.
λ¬Έμ κ° μ’
λ£λ μ΄μ λ 무μμ
λκΉ? μ¬κΈ°μλ κ΄λ ¨ λ°μ΄ μμ΅λλ€... xd
λ΄ λ¬Έμ λ λ€μκ³Ό κ°μ΅λλ€(μν μ½λ).
const [userStatus, setUserStatus]: any = React.useState([]);
const [userData, setUserData]: any = React.useState([]);
useEffect(() => {
setUserStatus(!userStatus);
return () => {};
}, [userData]);
λ°λΌμ μ½λμμμ κ°μ΄ userData
λ³κ²½ μ¬νμ΄ μμ λ userStatus
κ°μ λ³κ²½νκ³ μ΄ κ²½μ° userStatus
κ°μ νμΈνλ €λ©΄ depsμ μΆκ°ν΄μΌ ν©λλ€.
const [userStatus, setUserStatus]: any = React.useState([]);
const [userData, setUserData]: any = React.useState([]);
useEffect(() => {
setUserStatus(!userStatus);
return () => {};
}, [userData, userStatus]);
μ΄ μλ리μ€μμλ λμ΄ μλ 루νκ° λ©λλ€.
@spmsupun
useStateμ μ½λ°± μ€νμΌμ μ¬μ©νμ¬ useEffectμ μ’
μμ± λ°°μ΄μ userStatus λ³μλ₯Ό λμ
νμ§ μλλ‘ ν μ μμ΅λλ€.
useEffect(() => {
setUserStatus(prevState => !prevState);
return () => {};
}, [userData]);
κ·Έλ¦¬κ³ μ΄κ²μ κΈ°λ₯ μ λ°μ΄νΈ λΌκ³
μ루μ --> μ’ μμ±μ μν΄ λ§μ§λ§μ λμ€ν¨μΉλ₯Ό ββμΆκ°νμμμ€.
React Hook useEffectμ λλ½λ μ’ μμ±: 'dispatch'κ° μμ΅λλ€.useEffect(() => { axios.get('http://localhost:8000/api/future-registrations') .then((result) => { dispatch(initRegistrationsAction(result.data)); }); ** }, [dispatch]);**
@kennylbj μ΄κ²μ νλμ μνλ₯Ό λ€λ£° λ μ’μ΅λλ€. μ€μ μλ리μ€λ propsμ λλ€. λλ λΆλͺ¨λ‘λΆν° μνμ 보λ΄κ³ μμΌλ©° λ λ² λ³κ²½λμ΄ usereffectκ° λ λ² νΈμΆνμ§λ§ λ΄λΆμμ 리μ€λλ₯Ό μ€ννκ³ μμΌλ©° λ λ² μμ ν©λλ€.
@spmsupun νμ§λ§ μ΄μ 리μ€λμ λ±λ‘μ ν΄μ νκ³ μ’ μμ± λ°°μ΄μ λ³μκ° λ³κ²½λ λλ§λ€ μ 리μ€λλ₯Ό λ±λ‘νλ κ²μ λ§€μ° μ μμ μ΄λΌκ³ μκ°ν©λλ€(μ: propsμ userIdκ° λ³κ²½λλ©΄ 리μ€λλ λ³κ²½λμ΄μΌ ν¨). κ·Έλ¦¬κ³ μ΄ λμμ λ°μμ΄ κΈ°λνλ κ²μ λλ€.
μ¬μ ν 리μ€λλ₯Ό λ λ² νΈμΆνμ§ μμΌλ €λ©΄ μ λ¬λ propsμ λ μ κ²½μ μ¨μΌ νκ³ λ λλ§ μ€μ λ³κ²½λμ§ μλλ‘ ν΄μΌ ν©λλ€.
@kennylbj κΈμ λ±λ‘μ μ·¨μνμ§λ§ μ¬μ ν μ’μ μ΅κ΄μ μλλλ€.
리μ€λ ν΄λμ€μμ μ²λ¦¬ν΄μΌνλ€κ³ μκ°ν©λλ€.
μμΌ IDκ° κ°λλΌλ 리μ€λκ° λ λ² νΈμΆλλ κ² κ°μ΅λλ€.
λ€μ μν©μ΄ μΆ©μ‘±λλ©΄ μ΄κ²μ΄ μΌμ΄λμ§ μμ κ²μ΄λΌκ³ μκ°ν©λλ€.
ts
// call useEffect if and only if sockeId changed.
useEffect(() => {
const unregister = register(socketId);
return () => unregister(socketId);
}, [socketId])
λ€λ₯Έ λ λ μ€μ λ³κ²½λμ΄ μ΄ λμμ μΌμΌν€λ μ’ μμ± λ°°μ΄μ λ€λ₯Έ λ³μκ° μμ΅λκΉ?
μ 3 μ’ μμ±,νμ§λ§ λ€λ₯Έ λ°©λ²μΌλ‘ μμλ λλ€.
νΌμ
κ²½κ³ λ©μμ§μμ μ μν λλ‘ λ€μκ³Ό κ°μ΄ ν μ μμ΅λλ€.
const initFetch = useCallback(() => { dispatch(fetchPosts()); }, [dispatch]); useEffect(() => { initFetch(); }, [initFetch]);
μμ°, λΉεΈΈζθ°’δ½ π
π μλ μ½λ μ€λν«μ μ μκ² μ λ§ μ λ§μ΅λλ€.
κ΅¬μ± μμμμ λ§μ΄νΈ
const onInit = () => getUsers()
useEffect(onInit, [])
맀κ°λ³μ λ³κ²½ μ
const onInit = () => getUser(id)
useEffect(onInit, [id])
μ΅μ μ ν΄κ²° λ°©λ²: react-hooks/exhaustive-deps: "κΊΌμ§"
λλ μ΄ eslint κΈ°λ₯μ΄ μ μ©νλ€λ κ²μ κ²°μ½ λ°κ²¬νμ§ λͺ»νμ΅λλ€. νμ.
π μλ μ½λ μ€λν«μ μ μκ² μ λ§ μ λ§μ΅λλ€.
κ΅¬μ± μμμμ λ§μ΄νΈ
const onInit = () => getUsers() useEffect(onInit, [])
맀κ°λ³μ λ³κ²½ μ
const onInit = () => getUser(id) useEffect(onInit, [id])
μ νμ ¨μ΄μ.
λλ λ°μ λ¬Έμκ° @luojinghui μ μ¬μ© μ¬λ‘λ₯Ό μΆ©λΆν λ€λ£¨μ§ μλλ€κ³ μκ°ν©λλ€.
μ£Όμ΄μ§ ν¨μλ₯Ό νΈμΆνλ μ¬λ¬ κ°μ§ λ°©λ²μ΄ μμ΅λλ€. μ: setCenterPosition()
. μν λ³κ²½( useEffect
λ₯Ό ν΅ν΄ μ°κ²°λ¨), ν΄λ¦ νΈλ€λ¬(μ§μ νΈμΆ) λ±μ κ΄μ°°νμ¬ νΈμΆν μ μμ΅λλ€.
λ°μ λ¬Έμ μ μ
μ΄κ²μ΄ μΌλ°μ μΌλ‘ λ΄λΆ ν¨κ³Όμ νμν ν¨μλ₯Ό μ μΈνλ €λ μ΄μ
κ·Έλ¬λ μΌλ°μ μΌλ‘ μ€μ μμ μμλ ν΄λμ€ κ΅¬μ± μμ( this.setCenterPosition(...)
)μ μΈμ€ν΄μ€ λ©μλμμ μΌλ°μ μΌλ‘ νλ κ²μ²λΌ ν¨μλ₯Ό μ¬μ¬μ©ν΄μΌ νλ©° νν¬κ° μ€μ λ‘ μ 체 κΈ°λ₯μ μ ν©νμ§ κΆκΈν΄μ§κΈ° μμνμ΅λλ€. 볡μ‘ν κ΅¬μ± μμ.
μ€μ λ‘ νμ€νμ§ μμ§λ§ μλ§λ ν΄κ²°μ±
μ useCallback
const setCenterPosition = useCallback(() => {
...
}, [Stage, elePositionArr, setElePositionArr]);
useEffect() => {
...
}, [stageRef, Stage, currentIndex, setCenterPosition]);
...νμ§λ§ κ·Έκ²μ λμκ² μ’ λμ°ν©λλ€. κ·Έλ¦¬κ³ λ κΉ¨λν λ°©λ²μ΄ μκΈ°λ₯Ό λ°λλλ€. @gaearon μ΄ νμΈν μ μμκΉμ?
κ°μ λ¬Έμ μ μ§λ©΄νμ¬ useEffect
// eslint-disable-next-line react-hooks/exhaustive-deps
λμ μ΄ μ€μ μ¬μ©νμ¬ κ²½κ³ buλ₯Ό λΉνμ±νν μ μμ§λ§ μ¬μ©νκ³ μΆμ§ μμ΅λλ€.
μ¬κΈ° λ΄ μ½λκ° μμ΅λλ€
`const [items, setItems] = useState([
{
μ΄λ¦: "ν
μ€νΈ 1",
μμ΄λ: 1
},
{
μ΄λ¦: "ν
μ€νΈ 2",
μμ΄λ: 2
},
{
μ΄λ¦: "ν
μ€νΈ 3",
μμ΄λ: 3
},
{
μ΄λ¦: "ν
μ€νΈ 4",
μμ΄λ: 4
},
{
μ΄λ¦: "ν
μ€νΈ 5",
μμ΄λ: 5
}
]);
useEffect(() => {
μμ κ°κ²© ID = setInterval(() => {
setItems(shuffleArray(νλͺ©));
}, 1000);
λ°ν() => {
clearInterval(intervalId);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
μ΄ λ¬Έμ μ λν λμ ν΄κ²°μ±
μ μ΄λ¬ν κ²½μ°μ React Hooks μ¬μ©μ μ€λ¨νλ κ²μ΄μμ΅λλ€. κ΅¬μ± μμμ componentDidMount
μ κ°μ μν λ
Όλ¦¬ λ° μλͺ
μ£ΌκΈ° μ΄λ²€νΈκ° λ§μ΄ νμν κ²½μ° ν΄λμ€ κ΅¬μ± μμλ₯Ό μ¬μ©νκ³ λν΅μ νΌνμμμ€. ν΄λμ€ κ΅¬μ± μμλ μλ²½νκ³ μ΄ μ€λ λκ° μ¦λͺ
νλ κ²μ΄ μλ€λ©΄ 볡μ‘ν μν λ
Όλ¦¬ λλ μλͺ
μ£ΌκΈ° μ΄λ²€νΈκ° νμν λ React Hooksκ° μ΄λ₯Ό μμ ν λ체ν μ€λΉκ° λμ΄ μμ§ μλ€λ κ²μ
λλ€. React Hooksλ₯Ό μ¬μ©νλ κ²μ΄ ν¨μ¬ λ«μ΅λκΉ?).
μ λ React Hooksμ μ¬μ©μ useState
μ κ°μ κ°λ¨ν κ²μΌλ‘ μ ννμ¬ λΆμΈ νλκ·Έμ κ°μ κ²μ μ€μ ν©λλ€. κ΅¬μ± μμκ° useEffect
κ° νμν λ§νΌ 볡μ‘ν΄μ§λ©΄ ν΄λμ€ κ΅¬μ± μμκ° λ μ ν©νλ€λ μ νΈλ‘ κ°μ£Όν©λλ€.
(λͺ νμ±μ μν΄ νΈμ§λ¨).
μ΄κ²μ΄ νμ¬ λ΄ μ루μ μ λλ€.
const mounted = () => {
dispatch(something());
}
useEffect(mounted, []);
@ra30r react/issues/15865#issuecomment-651254164 κ°μ¬ν©λλ€.
κ°μ₯ μ μ©ν λκΈ
μμ² λͺ μ κ°λ°μκ° λμΌν λ¬Έμ μ μ§λ©΄νκ³ React κ°λ° νμ΄ μ€λ λλ₯Ό λ«κ³ λͺ¨λ μ¬λμ 무μν λ: