useEffect are as follows.
① Processing can be performed after rendering
(2) Execution timing can be controlled by the second argument of useEffect
③ Cancellation processing at the time of unmounting can be set
But conversely, if you don't need any of the above, is it okay to execute asynchronous processing without using useEffect?
For example, in the process of fetching data from the server with Ajax and displaying it on the component, I feel that it may not be necessary to use useEffect for the following reasons.
① Issuing an Ajax request does not have to wait for the end of rendering
(2) If the rendering of the component is controlled by React.memo etc., the execution timing can be controlled without useEffect
③ There is no particular processing when unmounting
The code in that case is as follows.
const [name, setName]= useState ('');
axios.get (`https://example.com/api/users/XXX`).then (res= >
setName (res.data.name));
return (<
div >
{name} <
/div >
);
@hinaloe Sample code added! Thank you.
denko2022-02-11 23:21:51-
Answer # 1
useEffect
You shouldn't always use, butuseEffect
It is better to use.Personally, when doing asynchronous processing
useCallback
I think it's okay to move even if you do it,useEffect
I understand that is a best practice.Sample code
The sample code below has a major problem.
The point is that a request is made for each rendering.const [name, setName]= useState (''); //↓ axios.get is executed every time the component is rendered. //In other words, a request is made for each rendering! axios.get (`https://example.com/api/users/XXX`).then (res= > setName (res.data.name)); return (< div > {name} < /div > );
- First
setName
Is executed, then React's re-rendering process runs. - When rendering
axios.get ()
Is executed
The API server is making useless requests, which is obviously a problem.
useEffect
When usinguseEffect
With, API requests won't run multiple times.const Example= ()= > { const [name, setName]= useState (''); //Executed only once after component mounting useEffect (()= > { let unmounted= false; async function fetchName () { //I used fetch instead of axios //https://developer.mozilla.org/ja/docs/Web/API/fetch const res= await fetch ('https://example.com/api/users/XXX'); if (! res.ok) { throw new Error (`unexpected status: $ {res.status}`); } const data= await res.body (); //If you setName after unmounted, it will prevent the memory from being released, so the debugger will be warned. if (! unmounted) { setName (data.name); } } fetchName (); return ()= > { unmounted= true; };; }, []); return < div > {name} < /div > ; };;
API request after user action (
useCallback
)Next, let's consider the case where the timing of the API request is after the button is clicked.
In the case belowuseCallback
Is used.//Load the name when the button is clicked const Example= ()= > { const [name, setName]= useState (''); const unmountRef= useRef (false); useEffect (()= > { return ()= > { unmountRef.current= true; };; }, []); const handleClick= useCallback (async ()= > { const res= await fetch ('https://example.com/api/users/XXX'); if (! res.ok) { throw new Error (`unexpected status: $ {res.status}`); } const data= await res.body (); //If you setName after unmounted, it will prevent the memory from being released, so the debugger will be warned. if (! unmountRef.current) { setName (data.name); } }, []); return ( ≪ div > ≪ button onClick= {handleClick} > Read name < /button > ≪ div > Name: {name} < /div > ≪ /div > ); };;
In this case, after unmounting
setName
To prevent it from runninguseRef
Is used to save the mount state.API request after user action (
useEffect
)It's pretty verbose, but it's an ideal implementation.
//Load the name when the button is clicked function reducer (state, action) { switch (action.type) { case "LOAD":return {... state, isLoading: true, };; case "SET_NAME": return { isLoading: false, name: action.payload, };; default: default: return state; } } function reset () { return { isLoading: false, name:'', };; } const Example= ()= > { const [state, dispatch]= useReducer (reducer, undefined, reset); const {isLoading, name}= state; useEffect (()= > { if (! isLoading) { return; } let unmounted= false; async function fetchName () { //I used fetch instead of axios //https://developer.mozilla.org/ja/docs/Web/API/fetch const res= await fetch ('https://example.com/api/users/XXX'); if (! res.ok) { throw new Error (`unexpected status: $ {res.status}`); } const data= await res.body (); //If you dispatch after being unmounted, it will prevent the memory from being released, so the debugger will be warned. if (! unmounted) { dispatch ({type: "SET_NAME", payload: data.name}); } } fetchName (); return ()= > { unmounted= true; };; }, [isLoading]); const handleClick= useCallback (async ()= > { dispatch ({type: "LOAD"}); }, []); return ( ≪ div > ≪ button onClick= {handleClick} > Read name < /button > ≪ div > Name: {name} < /div > ≪ /div > ); };;
In this last case
isLoading
Buttrue true
When it becomes, the API request is executed and the state of the component is updated.The amount of code required for implementation will increase, but considering maintainability such as ease of understanding the logic when reading the code,
useCallback
thanuseEffect
I think that the gunbai will go up. - First
- javascript : Why do I get a jsx file instead of js after building a project with webpack using babel
- javascript : render {routes} in react
- javascript : React. Unloading ads for 10 pieces
- javascript : How to restart an existing React app?
- javascript : The simplest code on React.js does not work
- javascript : React. Send a get request to the server when pressing Enter
- javascript : Running webPack 5 in development mode does not see html page
- javascript : Problem with Route
- javascript : JS: wrap links found inside a string in an element
- javascript : How to optimize useSelector redux
What code do you expect if you don't use useEffect? Please post the sample code!
hinaloe2022-02-11 23:21:51