I'm trying to learn React (with redux) so i'm making an app where i'm able to create workout plans, add workouts to them and then add exercises to a workout.
PlanListComponent
import { Button, Card, Typography } from "@material-ui/core/";
import { makeStyles } from "@material-ui/core/styles";
import DeleteIcon from "@material-ui/icons/Delete";
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { deletePlan, getPlans } from "../actions/plansActions";
import AddWorkouts from "./AddWorkouts";
const useStyles = makeStyles((theme) => ({}));
function PlansList() {
const classes = useStyles();
const { plans } = useSelector((state) => state.plans);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPlans());
}, [dispatch]);
return (
<div>
{plans.map((plan) => (
<Card key={plan._id}>
<Typography>{plan.name}</Typography>
<Typography>{plan._id}</Typography>
<div>
{plan.workouts.map((workout) => (
<li key={workout._id}>{workout.description}</li>
))}
</div>
<AddWorkouts plan={plan} />
<Button onClick={() => dispatch(deletePlan(plan._id))}>
<DeleteIcon /> Delete
</Button>
</Card>
))}
</div>
);
}
export default PlansList;
My PlansList component renders a card for every plan. Within this card it renders a list of workouts for every workout within that plan. After adding a workout to a plan, the PlansList component does not rerender. The added workout only shows after i refresh the page. I am guesing this happens because i have to update the state of the nested workout array in order to make React rerender my component.
These are my actions and reducers for adding a workout to a plan. The payload i am sending in my action is an array of objects.
Action
export const addWorkouts = (workouts, planId) => (dispatch, getState) => {
axios
.post(`/workouts/${planId}`, workouts, tokenConfig(getState))
.then(res =>
dispatch({
type: ADD_WORKOUTS,
id: planId
payload: res.data
}));
}
Reducer
const initialState = {
plans: [{
workouts: []
}],
isLoading: false,
};
export default function (state = initialState, action) {
switch (action.type) {
case ADD_WORKOUTS:
return {
...state,
plans: {
// guessing i should find the right plan by id here
...state.plans,
workouts: {
...state.plans.workouts,
workouts: state.plans.workouts.concat(action.payload)
}
}
};
default:
return state;
}
I've seen a lot of tutorials on how to update the state of nested arrays and tried a few different things, but i can't seem to find the right solution here.
Does anyone has any idea how to fix this issue?