Issue
As per Doc
useSelector(selector: Function, equalityFn?: Function)
useSelector accepts two params and second one is optional since by default it compare strict === reference equality check but not shallow equality.
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
}, shallowEqual)
Another is
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
})
In both Cases component rerendering when redux store state changes and also when local state changes then it will render (print console.log inside useSelector)
I really didn't understand exactly how it works
Full source code
import React, { useState } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { decrement, increment } from './store/actions'
export default function CounterHooks(props) {
const [submit, setSubmit] = useState(false)
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
}, shallowEqual)
const dispatch = useDispatch()
console.log("component rerendering");
const increments = () => {
dispatch(increment());
}
const decrements = () => {
dispatch(decrement());
}
const submitButton = () => {
console.log("component submit", submit);
setSubmit((previousState) => !previousState)
}
return (
<div>
<button onClick={increments} >Incrmeent Counter</button>
<br />
<button onClick={decrements} >Decrement Counter</button>
<br />
<button onClick={submitButton} >Submit</button>
<br />
<h2>total : {state.count}</h2> <br />
<h2>Submit:{String(submit)}</h2> <br />
</div>
)
}
MY question is how exactly second param works ?
Solution
In your example, it does not make a difference.
shallowEquals
makes sense when you select an object that might be similar in contents, but different by reference.
See these two objects:
const a = { foo: "bar" }
const b = { foo: "bar" }
console.log( a === b ) // will log false
console.log( shallowEquals(a, b)) // will log true
While a
and b
are two objects with similar shape and contents, they are not the same object.
Now shallowEquals
does a ===
comparison between a.foo
and b.foo
and since both are strings with the same content, a.foo === b.foo
will be true.
This does play a role if you create a new object in your selector, say
const result = useSelector((state) => {
return { a: state.foo.bar, b: state.baz.boo }
})
The result of this will always be a new object, so per default useSelector
will always assume they are different, even when state.foo.bar
and state.baz.boo
actually did not change.
If you use a shallowEqual
, useSelector
will look at the direct (only 1 level deep) child properties of the objects and compare those. Then it will notice that they are in fact equal and not rerender.
Answered By - phry
Answer Checked By - - Robin (ReactFix Admin)