score:202
the main difference between both is :
usestate
causes re-render, useref
does not.
the common between them is, both usestate
and useref
can remember their data after re-renders. so if your variable is something that decides a view layer render, go with usestate
. else use useref
i would suggest reading this article.
score:0
you can also use useref
to ref a dom element (default html attribute)
eg: assigning a button to focus on the input field.
whereas usestate
only updates the value and re-renders the component.
score:0
it really depends mostly on what you are using the timer for, which is not clear since you didn't show what the component renders.
if you want to show the value of your timer in the rendering of your component, you need to use usestate. otherwise, the changing value of your ref will not cause a re-render and the timer will not update on the screen.
if something else must happen which should change the ui visually at each tick of the timer, you use usestate and either put the timer variable in the dependency array of a useeffect hook (where you do whatever is needed for the ui updates), or do your logic in the render method (component return value) based on the timer value. setstate calls will cause a re-render and then call your useeffect hooks (depending on the dependency array). with a ref, no updates will happen, and no useeffect will be called.
if you only want to use the timer internally, you could use useref instead. whenever something must happen which should cause a re-render (ie. after a certain time has passed), you could then call another state variable with setstate from within your setinterval callback. this will then cause the component to re-render.
using refs for local state should be done only when really necessary (ie. in case of a flow or performance issue) as it doesn't follow "the react way".
score:0
useref() only updates the value not re-render your ui if you want to re-render ui then you have to use usestate() instead of usere. let me know if any correction needed.
score:0
the main difference between usestate and useref are -
the value of the reference is persisted (stays the same) between component re-rendering,
updating a reference using
useref
doesn't trigger component re-rendering. however, updating a state causes component re-renderingthe reference update is synchronous, the updated referenced value is immediately available, but the state update is asynchronous - the value is updated after re-rendering.
to view using codes:
import { usestate } from 'react';
function logbuttonclicks() {
const [count, setcount] = usestate(0);
const handle = () => {
const updatedcount = count + 1;
console.log(`clicked ${updatedcount} times`);
setcount(updatedcount);
};
console.log('i rendered!');
return <button onclick={handle}>click me</button>;
}
each time you click the button, it will show i rendered!
however, with useref
import { useref } from 'react';
function logbuttonclicks() {
const countref = useref(0);
const handle = () => {
countref.current++;
console.log(`clicked ${countref.current} times`);
};
console.log('i rendered!');
return <button onclick={handle}>click me</button>;
}
i am rendered will be console logged just once.
score:1
if you store the interval id, the only thing you can do is end the interval. what's better is to store the state timeractive
, so you can stop/start the timer when needed.
function timer() {
const [timeractive, settimeractive] = usestate(true);
useeffect(() => {
if (!timeractive) return;
const id = setinterval(() => {
// ...
});
return () => {
clearinterval(intervalid);
};
}, [timeractive]);
// ...
}
if you want the callback to change on every render, you can use a ref to update an inner callback on each render.
function timer() {
const [timeractive, settimeractive] = usestate(true);
const callbackref = useref();
useeffect(() => {
callbackref.current = () => {
// will always be up to date
};
});
useeffect(() => {
if (!timeractive) return;
const id = setinterval(() => {
callbackref.current()
});
return () => {
clearinterval(intervalid);
};
}, [timeractive]);
// ...
}
score:1
- counter app to see
useref
does not rerender
if you create a simple counter app using useref to store the state:
import { useref } from "react";
const app = () => {
const count = useref(0);
return (
<div>
<h2>count: {count.current}</h2>
<button
onclick={() => {
count.current = count.current + 1;
console.log(count.current);
}}
>
increase count
</button>
</div>
);
};
if you click on the button, <h2>count: {count.current}</h2>
this value will not change because component is not re-rendering. if you check the console console.log(count.current)
, you will see that value is actually increasing but since the component is not rerendering, ui does not get updated.
if you set the state with usestate
, clicking on the button would rerender the component so ui would get updated.
- prevent the unnecessary re-renderings while typing into
input
.
rerendering is an expensive operation. in some cases you do not want to keep rerendering the app. for example, when you store the input value in state to create a controlled component. in this case for each keystroke you would rerender the app. if you use the ref
to get a reference to the dom element, with usestate
you would rerender the component only once:
import { usestate, useref } from "react";
const app = () => {
const [value, setvalue] = usestate("");
const valueref = useref();
const handleclick = () => {
console.log(valueref);
setvalue(valueref.current.value);
};
return (
<div>
<h4>input value: {value}</h4>
<input ref={valueref} />
<button onclick={handleclick}>click</button>
</div>
);
};
- prevent the infinite loop inside
useeffect
to create a simple flipping animation, we need to 2 state values. one is a boolean value to flip or not in an interval, another one is to clear the subscription when we leave the component:
const [isflipping, setisflipping] = usestate(false);
let flipinterval = useref<returntype<typeof setinterval>>();
useeffect(() => {
startanimation();
return () => flipinterval.current && clearinterval(flipinterval.current);
}, []);
const startanimation = () => {
flipinterval.current = setinterval(() => {
setisflipping((prevflipping) => !prevflipping);
}, 10000);
};
setinterval
returns an id and we pass it to clearinterval
to end the subscription when we leave the component. flipinterval.current
is either null or this id. if we did not use ref
here, everytime we switched from null to id or from id to null, this component would rerender and this would create an infinite loop.
- if you do not need to update ui, use
useref
to store state variables.
let's say in react native app, we set the sound for certain actions which have no effect on ui. for one state variable it might not be that much performance savings but if you play a game and you need to set different sound based on game status.
const popsoundref = useref<audio.sound | null>(null);
const pop2soundref = useref<audio.sound | null>(null);
const winsoundref = useref<audio.sound | null>(null);
const losssoundref = useref<audio.sound | null>(null);
const drawsoundref = useref<audio.sound | null>(null);
if i used usestate
, i would keep rerendering every time i change a state value.
score:5
basically, we use usestate in those cases, in which the value of state should be updated with re-rendering.
when you want your information persists for the lifetime of the component you will go with useref because it's just not for work with re-rendering.
score:8
useref
is useful when you want to track value change, but don't want to trigger re-render or useeffect
by it.
most use case is when you have a function that depends on value, but the value needs to be updated by the function result itself.
for example, let's assume you want to paginate some api result:
const [filter, setfilter] = usestate({});
const [rows, setrows] = usestate([]);
const [currentpage, setcurrentpage] = usestate(1);
const fetchdata = usecallback(async () => {
const nextpage = currentpage + 1;
const response = await fetchapi({...filter, page: nextpage});
setrows(response.data);
if (response.data.length) {
setcurrentpage(nextpage);
}
}, [filter, currentpage]);
fetchdata
is using currentpage
state, but it needs to update currentpage
after successful response. this is inevitable process, but it is prone to cause infinite loop aka maximum update depth exceeded error
in react. for example, if you want to fetch rows when component is loaded, you want to do something like this:
useeffect(() => {
fetchdata();
}, [fetchdata]);
this is buggy because we use state and update it in the same function.
we want to track currentpage
but don't want to trigger usecallback
or useeffect
by its change.
we can solve this problem easily with useref
:
const currentpageref = useref(0);
const fetchdata = usecallback(async () => {
const nextpage = currentpageref.current + 1;
const response = await fetchapi({...filter, page: nextpage});
setrows(response.data);
if (response.data.length) {
currentpageref.current = nextpage;
}
}, [filter]);
we can remove currentpage
dependency from usecallback
deps array with the help of useref
, so our component is saved from infinite loop.
Source: stackoverflow.com
Related Query
- React useState not updating because of useRef
- best practice to sync useRef with useState in React
- React useRef hook: useRef value not be used by a useState function
- Set types on useState React Hook with TypeScript
- How to use callback with useState hook in react
- React Hooks: Why is .current null for useRef Hook?
- React Hooks - using useState vs just variables
- Why React Hook useState uses const and not let
- React useState hook event handler using initial state
- How target DOM with react useRef in map
- React hooks useState Array
- ReactJS - prevState in the new useState React hook?
- How to use React useRef hook with typescript?
- Why React useState with functional update form is needed?
- React - useState not setting initial value
- React - useState - why setTimeout function does not have latest state value?
- React - useRef with TypeScript and functional component
- React hooks: Why do several useState setters in an async function cause several rerenders?
- useState to update multiple values in React
- react usestate hooks error: argument of type 'yyy' is not assignable to parameter of type 'setstateaction<xx>'
- React - Is useState 's setter function able to change?
- React hook useRef not working with styled-components and typescript
- How to prevent race conditions with react useState hook
- New To React Hook useState Is Returning Undefined
- React efficiently update object in array with useState hook
- useState with boolean value in react
- Show the name of state variables from useState in React Developer Tool
- React hooks useState not updating with onChange
- React useState - using one State per component vs multiples states?
- useMemo vs useState for React hooks constants
More Query from same tag
- React Redux error: default parameters should be last default-param-last
- switch icons on button click in react
- Stop one children component re-render
- TypeError: <...> is not a function
- how to call conditional useQuery hook in react/apollo
- React Native 0.57.x <Image/> large images low quality
- Nx.dev Gatsby throws error in plugin gatsby-plugin-translate-urls - Support for the experimental syntax 'jsx' isn't
- React hooks setState not updating immediately
- ReactJs: How to replace html and string template with a component?
- How to display text/button in react-big-calendar cell?
- Unexpected token when using import type
- Helmet errors with renderStatic
- Z-index not adding item to the top
- isomorphic reactjs cdn assets
- How to connect firebase firestore to redux
- Spread syntax in Redux configureStore (Redux Toolkit)
- How to resize material-ui's tabs
- I have an <Add /> component that is called in two different pages, but only one of them is receiving the add count prop passed to it in React JS
- How to pass colors as props to a linear gradient background property in styled components
- Onclick calling functions diffrences
- Why does the react-sortable-hoc basic example fail to compile with typescript?
- React function component prop default with TypeScript
- Change a value in a table by clicking on it
- Secure way to use dangerouslySetInnerHTML inside my react SharePoint Modern web part
- history.listen() replacement in react router V6
- styling a caption to the center of a slider in react
- How Can I change the property of components of React?
- How to write unit testing for functions in React js?
- How to use spring boot java to properly use axios.post from React
- React Component running after I change page