I am creating a React application with Saga middleware. And I have few doubts to clarify.
On the first mount, why is it we are destructing an unknown prop
const { onGetPhonesAndTablets } = props
which is not passed from the Redux Store (State Container).Why is it required to
setPhoneAndTabletsList(phonesAndTablets)
before dispatching an actiononGetPhonesAndTablets
. As the propphonesAndTablets
will have its value after dispatching an action i.e.,onGetPhonesAndTablets
const Home = props => {
const {
phonesAndTablets
} = props
const [phonesAndTabletsList, setPhoneAndTabletsList] = useState([]);
useEffect(() => {
const {
onGetPhonesAndTablets
} = props
setPhoneAndTabletsList(phonesAndTablets)
onGetPhonesAndTablets()
}, [])
useEffect(() => {
if (!isEmpty(phonesAndTablets)) setPhoneAndTabletsList(phonesAndTablets)
}, [phonesAndTablets])
return (
<React.Fragment>
<ProductCategoryList list={phonesAndTabletsList}/>
</React.Fragment>
)
}
Home.propTypes = {
phonesAndTablets: PropTypes.array,
onGetPhonesAndTablets : PropTypes.func
}
const mapStateToProps = ({ home }) => ({
phonesAndTablets: home.phonesAndTablets
})
const mapDispatchToProps = dispatch => ({
onGetPhonesAndTablets: () => dispatch(getPhoneAndTablets())
})
export default connect(mapStateToProps, mapDispatchToProps)(Home)
CodePudding user response:
I'm not entirely sure why this app uses a local state to store the redux state, which is passed as a prop. Seems redundant, not to mention bad for performance.
There is a selector hook, which lets components access individual pieces of redux state. useSelector(state => state.home.phonesAndTablets)
.
You can also pass a second argument,
shallowEqual
, which makes the comparison function do a value comparison, as opposed to reference comparison. This avoids unnecessary re-renders due to objects/arrays whose contents are equal, but whose references point to different objects. Remember that['a'] !== ['a']
in JS.
There is also a dispatch hook to do the same for actions. useDispatch(action)
. Then you can do
const list = useSelector(state => state.home.phonesAndTablets, shallowEqual)
const dispatch = useDispatch()
useEffect(() => {
dispatch(getPhoneAndTablets())
}, [])
return (
<>
<ProductCategoryList list={list ?? []} />
</>
)
I would personally add a check if the list is empty before fetching a new list, but maybe the app is supposed to fetch a new list whenever Home
is mounted. I have no idea.
CodePudding user response:
Since, the above code seems redundant as the state is already managed and handled by the State Container (Redux Store). So I tried removing redundant codes.
Personally I prefer mapStateToProps
to selectors
.
const Home = props => {
const {
phonesAndTablets,
onGetPhonesAndTablets
} = props
useEffect(() => {
onGetPhonesAndTablets()
}, [])
return (
<React.Fragment>
<ProductCategoryList list={phonesAndTablets ? phonesAndTablets : ''}/>
</React.Fragment>
)
}
Home.propTypes = {
phonesAndTablets: PropTypes.array,
onGetPhonesAndTablets : PropTypes.func
}
const mapStateToProps = ({ home }) => ({
phonesAndTablets: home.phonesAndTablets
})
const mapDispatchToProps = dispatch => ({
onGetPhonesAndTablets: () => dispatch(getPhoneAndTablets())
})
export default connect(mapStateToProps, mapDispatchToProps)(Home)