React create custom Hook that never rebuild - reactjs

I am using a custom hook without a state and want to "persist" the hook.
The hook is called useMessage() and should only be rebuilt in the first render cycle since i don't use any state in there.
I want to have a global hook the redux hook useDispatch().
How is that possible?
EDIT:
I just want to have 1 reference / a singelton of my hook to not get rerendered all the time!
Is there any way to memorize the hook? My goal is that i am able to add the hook in dependencies of e.g. useEffect() and this never will cause a rerun of the useEffect(). Just like useDispatch / useRef / ...

I'm not sure if this is what you mean - but try this:
const [myValue] = useState(() => myInitialValue);
useState accepts a callback function as a parameter, which will only be executed on first render for your component. For all future renders, it will return the first value that was returned from your function.

Well the answer is - you just can't. A custom hook will always rerun if the component where you included it runs again.
What I expected: Just return a memorized Value (useMemo) containing the dependencies in the array. This will keep the custom hook simple and only a small part will rerun.

Related

Dynamic Callback on useState React?

I want to run a function ONLY some of the time I update a state values using setter function of useState hook in react, how would I do it?
In my code flow, I update the state value in multiple places, but need to run callbacks only on few of them, because of this I can't use the useEffect way which is widely prescribed.

React hooks queries

I have the following queries -
What's the difference between useEffect, useMemo and useCallback hooks ? I have gone through many examples and explanations but still am not clear on their difference. All I know is that each executes only when at least one of their dependencies change.
If useRef hook allows us to persist with values between re-renders, why not use a simple variable (not a state) for the same ? I read somewhere that if not changed manually, useRef will have the same value all the time. Can't we achieve this with a simple variable ?
tl;dr
useMemo fired immediately, useCallback not.
local variables a not persisted between renders
Explained
useMemo and useCallback area really very same. The difference between them are mentioned in the hooks names.
useMemo is created for calculating some heavy things (like taking some very long list and mapping it in another) and storing it for some time – as documentation says React can drop useMemo result and make hook to run again. When component is rendering first time, all useMemos continuously runs calculations and their results may be used during the render. When rendering next times (if no hook dependencies changed) React do not call passed function but just using memorized result.
useCallback is created just for preserving variable references to functions that is passed as first argument. It is very helpful when callback, created with that hook is passed to some children components cause persistent variable reference do not invalidates memorized components.
Small example:
const app = () => {
console.log('app render starts')
const title = React.useMemo(() => {
console.log('running calcualtion!')
return 'Hello world'
}, [])
console.log('app render continues')
const handleClick = React.useCallback(() => {
console.log('handling click')
}, [])
console.log('app render continues again')
return <div onClick={handleClick}>{title}</div>
}
/*
Output after mounting app:
- app render starts
- running calcualtion!
- app render continues
- app render continues again
And after clicking div:
- handling click
*/
About useRef
React functional components are functions that runs again on every component render. Without hooks that functions are totally pure and unable to contain any state or preserve variables value – all function-scoped variables are created on every render again.
Hooks know which component are currently being rendered, so hooks able to store some data about component and get it back when component re-rendered.
In lot of cases useRef really are just a way to persist value between renders. As described above, you can't achieve that with simple variables inside of component's function. It could be achieved with some global variable declared outside of component. It even may be better choice if variable value do not depends one component mount/unmount which are handled by useRef.

React useEffect/componentDidMount vs. state hook + function

It seems to me that one could replace useEffect/componentDidMount with a state hook and function components. For example, if I wanted to make a fetch in useEffect or componentDidMount, I could simply create a function component that rendered the component that needed fetching, add the fetching method in the function (which will execute upon rendering) which modifies a state hook (so that once the data arrives, the page will re-render with the data). Since React has selective rendering, any other part of the function component that gets updated won't cause an unnecessary fetch.
Am I correct in saying this? Are there any other specific instances where useEffect/componentDidMount is strictly better?
Am not sure why you want to replace componentDidMount in class component or useEffect with a custom function for the use case you highlighted but those two are different in terms of behavior, componentDidMount is one functionality that useEffect provides in function component. useEffect is a combination of componentDidMount and componentWillUnmount and you can have mulitple useEffect on one function component. useEffect accept array of values that could make it run again, all you do is specify those value for that particular useCase you wanted and whenever that values changes the useEffect is called, for UI changes you attach your useState to your logic and if followed accordingly you wont get unnecessary fetch request, if you want useEffect to be called just once then attach just an empty array like this useEffect(()=>{//your fetch logic here },[])

Why am I getting an infinite loop inside the component as state is globally managed?

I'm working with redux saga and redux toolkit. In the EachUser component, I don't understand why the component is mounting over and over again if I don't use the useEffect hook. Could someone help me understand why it is.
I'm not changing any props or state so I don't think infinite loop should happen but it is happening.
Here is the link to my code sandbox: Redux Saga With Redux toolkit
Happens following:
When you are trying to dispatch your FETCH_SINGLE_USER action on the top level of your functional component it will be executed on each render cycle (your function is re-rendered(executed) each time when props or state changed, also it will be re-rendered when the parent component is re-rendered (if you don't use React.memo).
So when you are dispatching your action on the top level of your functional component it will
fetch user from the server
->
update your store
->
updated store will cause re-render of the component as you are selecting updated state with useSelector
->
fetch user from the server action dispatched again (we are inside of the infinite loop)
So why we need useEffect - it is the hook that helps us to make some actions on special conditions. In the second parameter, you should put an array of dependencies, once dependency changed it will cause hook rerun. If the array is empty - hook will be executed only once when your functional component mounted. Also you can return cleanup function that will be executed, once your component unmounted. More documentation on useEffect hook here
try to remove dispatch from the array of dependencies
useEffect(() => {
dispatch({ type: sagaActions.FETCH_SINGLE_USER, userId });
}, [userId]);
calling a function inside useEffect and specifying it in an array of dependencies can cause an infinite rerender

React 'useEffect' hook replaces how many lifecycle methods?

How many lifecycle methods can be replaced by React useEffect?
I found an article on the useEffect hook that claims that it can replace only three, i.e. componentDidMount, componentDidUpdate and componentWillUnmount.
What about others?
Nope that's pretty much it, though it comes close to componentWillUpdate when you return a function and dont pass dependencies (it just doesn't run before the first render)
It's a really simple hook when you think about. The rules are pretty straightforward:
The function you pass to useEffect:
runs after every render, unless you provide a dependency array.
If you provide in a dependency array, it runs on first render, and then whenever the dependencies change.
The function your return from your useEffect function:
Is run before each render (except the very first) unless you provide a dependency array.
If you provide a dependency array, it is run before a render where the dependencies have changed, or the component unmounts.
It's probably best not to think about lifecycle events it replaces. Instead think about these 4 rules and how get them to run your functions when you want.
That is actually all. useEffect() is called once component is mounted and than on every state update. If you want to use it as componentWillUnmout you have to return a cleanup function like so
useEffect(() => {
//something you want to do
return () => console.log('cleanup is running');
});

Resources