Building an app for Gf's birthday - having trouble updating state in Redux

Viewed 49

So I'm building out a Gardening app for my girlfriends birthday to help her keep track of her garden, and my deadline (lol) is fast approaching! Basic implementation for version 1 is almost complete, but I'm with getting the data I want to appear without refreshing the page. This is my first time using Redux / trying to implement user authentication, so I'm probably just being dumb, BUT:

Essentially, the way the app is currently built, I get a bunch of data about the plants in the garden from state:

const plants = useSelector(state => state.plant.plants);

Then inside of my useEffect hooks, after the user has been authenticated, I filter through the list of plants to create a new list, with only the plants that were added by that specific user:

useEffect(() => {
dispatch(getPlants()); }, [dispatch]);
useEffect(() => { if (user && isAuthenticated) { const usersGarden = plants.filter(plant => plant.addedBy._id === user._id) setGarden(usersGarden) } }, [user, isAuthenticated, plants])

This new, user specific list of plants is supposed to be stored in state (garden and setGarden), and it is... the problem is that it won't appear until I've refreshed the page once.

This is what happens, in order:

While logged out:- My "state" console.log immediately shows data- The "plants" console.log (which is the useSelector hook that gets plants from state) eventually gets the plants, though it's logged as empty twice (I'm also not sure why these get logged so many times)- Garden is empty

Console/UI image: https://ibb.co/nrSPf0N

  1. After logging in:- State and plants console logs have data- Garden console.log still doesn't have the filtered list of the user's plants :((((((((

Console/UI image: https://ibb.co/VYP6BZF

  1. After logging in and refreshing the page once:-garden suddenly has the data that I want, and everything magically appears (If only I didn't have to refresh)

Console/UI image: https://ibb.co/6gH5z12

What am I doing wrong? =/

Full code:

import React, { useState, useEffect } from 'react';
import { Container, Card, CardBody, CardTitle, Button, Row, Col } from 'reactstrap';
import { useSelector, useDispatch } from 'react-redux';
import { getPlants, deletePlant } from '../actions/plantActions';
import PlantModal from './PlantModal';
import PlantDetailModal from './PlantDetailModal';


export const Garden = () => {
  const plants = useSelector(state => state.plant.plants);
  const dispatch = useDispatch();
  const auth = useSelector(state => state.auth);
  const { user, isAuthenticated } = auth;
  const [garden, setGarden] = useState([])

  console.log('state', useSelector(state => state))
  console.log('plants', plants)

  useEffect(() => {
    dispatch(getPlants());
  }, [dispatch]);

  useEffect(() => {
    if (user && isAuthenticated) {
      const usersGarden = plants.filter(plant => plant.addedBy._id === user._id)
      setGarden(usersGarden)
    }
  }, [user, isAuthenticated, plants])

  console.log('garden', garden)


  if (user && isAuthenticated) {
    return (
      <div>
        <Row>
          <Col xs="auto" className="mt-1">
            <h1 style={{ fontSize: "2.5rem", color: "#ffffb5" }}>{user ? user.name : null}'s Garden</h1>
          </Col>
          <Col className="py-2 text-right">
            <PlantModal />
          </Col>
        </Row>
        <Container fluid style={{ border: "3px solid #ffffb5", backgroundColor: "#99b898", borderRadius: "4px" }}>
          <Row>
            {garden.map(({ _id, name, description, growingZone, grownFromSeed, heirloom, idealTemp, imageURL, plantingDate, scientificName, seedDepth, soilType, spacing, sproutsIn, sunlight, timeToHarvest, watering }) => (
              <Col key={_id} className="my-3 d-flex justify-content-center">
                <Card className="text-center" body style={{ width: "275px", maxWidth: "275px" }}>
                  <Row className="text-right" style={{ marginTop: "-12px" }}>
                    <Col>
                      {isAuthenticated ? (
                        <Button
                          close
                          onClick={() => {
                            dispatch(deletePlant(_id));
                          }}
                        >
                        </Button>
                      ) : null}
                    </Col>
                  </Row>
                  <Row>
                    <Col>
                      <CardTitle>
                        <h4>{name}</h4>
                        <hr />
                        <h6 className="font-italic text-muted">{scientificName}</h6>
                      </CardTitle>
                    </Col>
                  </Row>
                  <CardBody className="p-0">
                    {<img className="rounded mt-3 mb-0 p-0" style={{ width: "230px", maxWidth: "230px" }} src={imageURL} alt="plant"></img> || <div className="rounded mb-4" style={{ width: "200px", height: "100px", backgroundColor: "seagreen" }}></div>}
                    <PlantDetailModal 
                        name={name} 
                        description={description} 
                        growingZone={growingZone} 
                        grownFromSeed={grownFromSeed} 
                        heirloom={heirloom} 
                        idealTemp={idealTemp} 
                        imageURL={imageURL} 
                        plantingDate={plantingDate} 
                        scientificName={scientificName} 
                        seedDepth={seedDepth} 
                        soilType={soilType} 
                        spacing={spacing} 
                        sproutsIn={sproutsIn} 
                        sunlight={sunlight} 
                        timeToHarvest={timeToHarvest} 
                        watering={watering} />
                  </CardBody>
                </Card>
              </Col>
            ))}
          </Row>
        </Container>
      </div >
    )
  }

  return <h1 className="text-white text-center mt-5 font-italic pt-5">~ Please Sign In ~</h1>
}

export default Garden;

My first time posting for help here, hopefully I provided enough info without being too long winded, and I really appreciate any help you might have for me! I'm stumped.

Thanks for your time. :)

Edit: Reducers:

import {
  GET_PLANTS,
  ADD_PLANT,
  DELETE_PLANT,
  PLANTS_LOADING
} from '../actions/types';

const initialState = {
  plants: [],
  loading: false
};

export default function (state = initialState, action) {
  switch (action.type) {
    case GET_PLANTS:
      return {
        ...state,
        plants: action.payload,
        loading: false
      };
    case DELETE_PLANT:
      return {
        ...state,
        plants: state.plants.filter(plant => plant._id !== action.payload)
      };
    case ADD_PLANT:
      return {
        ...state,
        plants: [action.payload, ...state.plants]
      };
    case PLANTS_LOADING:
      return {
        ...state,
        loading: true
      };
    default:
      return state;
  }
}
0 Answers
Related