Text Error
Text Error

Reputation: 41

useEffect as componentDidUpdate with multiple dependencies

How to conditional update my states?
if breakfast is not empty i want to update my Breakfast state,

if lunch is not empty i want to update my Lunch state,

if diner is not empty i want to update my Diner state,

if snack is not empty i want to update my Snack state,

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { state_breakfast, state_lunch, state_diner, state_snack } from '../../../redux/selectors/meal';

import Card from './Card';
import Buttons from './Buttons';
import isEmpty from '../../common/utils/isEmpty';

const Meals = ({ breakfast, lunch, diner, snack }) => {
  const [state, setState] = useState({ Breakfast: false, Lunch: false, Diner: false, Snack: false });
const { Breakfast, Lunch, Diner, Snack } = state;

useEffect(() => {
 if(!isEmpty(breakfast)) setState({ ...state, Breakfast: true });
},[breakfast]);

 // useEffect(() => {
 //   if(!isEmpty(breakfast)) setState({ ...state, Breakfast: true });
 //   if(!isEmpty(lunch)) setState({ ...state, Lunch: true });
 //   if(!isEmpty(diner)) setState({ ...state, Diner: true });
 // },[breakfast, lunch, diner, snack]);

  return(
    ....
  )

 const mapStateToProps = createStructuredSelector({
   breakfast: state_breakfast,
   lunch: state_lunch,
   diner: state_diner,
   snack: state_snack
  });

 export default connect(mapStateToProps, null)(Meals);

problem is, its update just 1 state

any help is welcome, Thank you

Upvotes: 1

Views: 899

Answers (2)

Adolfo Onrubia
Adolfo Onrubia

Reputation: 1831

You have 2 (or more) options to achieve that:

Option 1

handle each state inidividually:

const Meals = ({ breakfast, lunch, diner, snack }) => {

  const [breakfast, setBreakfast] = useState(breakfast);
  const [lunch, setLunch] = useState(lunch);
  const [dinner, setDinner] = useState(diner);
  const [snack, setSnack] = useState(snack);

useEffect(() => {
  if (breakfast) setBreakfast(true);
  if (lunch) setLunch(true);
  if (dinner) setDinner(true);
  if (snack) setSnack(true);
}, [breakfast, lunch, dinner, snack])

Option 2

function reducer(state, action) {
  return { ...state, ...action };
}

const Meals = ({ breakfast, lunch, dinner, snack }) => {
  const [state, setState] = useReducer(reducer, { breakfast, lunch, diner, snack });

useEffect(() => {
  setState({ breakfast, lunch, dinner, snack });
}, [breakfast, lunch, dinner, snack])

I recommend to use useReducer but handle it with a function passing the change.

Upvotes: 1

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196026

The problem is that you are re-using state for each setState.

So all the updates in a single pass re-use the current state and reset the previous values set in the same pass.

Use

useEffect(() => {
  let updates = {};
  if (!isEmpty(updateOne)) updates.one = true;
  if (!isEmpty(updateTwo)) updates.two = true;
  if (!isEmpty(updateTree)) updates.tree = true;
  if (!isEmpty(updateFour)) updates.four = true;

  setState({
    ...state,
    ...updates
  });
}, [updateOne, updateTwo, updateTree, updateFour]);

Upvotes: 1

Related Questions