I have experienced useEffect function from React hook. When I use it with useSelector from React-redux, it worked so weird.
const initialState = { a: 0 };
function mainReducer(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case 'A': return { ...state, a: payload }
default:
return state;
}
}
function MyComponent(props) {
const { a } = useSelector(state => state.mainReducer);
const dispatch = useDispatch();
useEffect(() => {
console.log('did mount: ', a);
dispatch({ type: 'A', payload: 1 })
}, []);
useEffect(() => {
console.log('use effect: ', a);
dispatch({ type: 'A', payload: a });
}, [a])
return (<View style={styles.container}>
<Text style={styles.text}>{a}</Text>
</View>);
};
Log:
did mount ran: 0
useEffect ran: 0
The last result is variable 'a' = 0
As I understand,
After the first render, both effect ran sequentially in their order in the code.
(Step 1) So the first effect run fist -> log 'did mount ran: 0'. Then it dispatch value 1 to store
(Step 2) The second effect run after -> log 'did mount ran: 0'. Then it dispatch value 0 to store
But what I don't understand is the second effect must track the change from variable 'a', so there will be:
In the following render time:
(Step 3) the second useEffect should be run when the value 'a' change from 0 to 1 (from Step 1).
And then:
(Step 4) it should have the third re-render when the value change again from 1 to 0 (from Step 2)
So the log should be:
did mount ran: 0
useEffect ran: 0
useEffect ran: 1
useEffect ran: 0
Could you please explain to me what I'm missing? Thank you
Empty dependency array So what happens when the dependency array is empty? It simply means that the hook will only trigger once when the component is first rendered. So for example, for useEffect it means the callback will run once at the beginning of the lifecycle of the component and never again.
You can add the state variables you want to track to the hook's dependencies array and the logic in your useEffect hook will run every time the state variables change. Copied! import {useEffect, useState} from 'react'; const App = () => { const [count, setCount] = useState(0); useEffect(() => { console.
The warning "React Hook useEffect has a missing dependency" occurs when the useEffect hook makes use of a variable or function that we haven't included in its dependencies array. To solve the error, disable the rule for a line or move the variable inside the useEffect hook.
Side Effect Runs After Props Value Change Just like the state, we can also use props as a dependency to run the side effect. In this case, the side effect will run every time there is a change to the props passed as a dependency. useEffect(() => { // Side Effect }, [props]);
Your both dispatch are called after first render so even before your second render value is 0 so your second useEffect won't be able detect change as there is no change.
Let's see what is happening in your render method
First Render:
a = 0
first useEffect: dispatch({ a : 1 })
second useEffect: dispatch({ a : 0 })
so now in your redux store a is 0.
Second Render
a = 0
first useEffect: doesn't run as there is no dependency
second useEffect: doesn't run as a hasn't changed.
useSelector(state => state.mainReducer);
it doesn't make any sense
there should be a simple state transformation (subselection)
const a = useSelector(state => state.a)
taken directly from redux docs:
const counter = useSelector(state => state.counter)
you can see effect (from store change) with slightly changed component
function MyComponent(props) {
const a = useSelector(state => state.a);
const dispatch = useDispatch();
console.log('render: ', a);
useEffect(() => {
console.log('use effect: ', a);
dispatch({ type: 'A', payload: a });
}, [a])
useEffect(() => {
console.log('did mount: ', a);
dispatch({ type: 'A', payload: 1 })
}, []);
return (<View style={styles.container}>
<Text style={styles.text}>{a}</Text>
</View>);
};
It should result in log:
render: 0
// initial state use effect: 0
// first effect run 0
... processed in store by reducer but results in the same state ...a
readed from state on the beginning of render did mount: 0
// 'old' a
1
... changed state in redux store .... rendered text 0
...
...
// useSelector
forces rerendering - change detected
render: 1
// latest dispatched value, processed by reducers into new state, rereaded by selector use effect: 1
// useEffect
works AS EXPECTED as an effect of a
change 1
...
...
Of course dispatch from other component will force update in this component ... if value will be different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With