0

Hey folks really hope someone can help me here. I'm successfully updating my object in my mongo cluster, it updates but it does not render that update straight away to the browser. It will only update after a reload or when I run my update function again, it doesn't fetch that update straight away and I can't understand why. Does anyone have any suggestions? I'm using context and reducer.

PlantDetails

 import { usePlantsContext } from "../hooks/usePlantsContext";
    import formatDistanceToNow from "date-fns/formatDistanceToNow";
    import { useState } from "react";
    import CalendarComponent from "./CalendarComponent";
    const PlantDetails = ({ plant }) => {
      const [watered, setWatered] = useState(false)
      const [newWaterDate, setNewWaterDate] = useState("")
      const { dispatch } = usePlantsContext();
      const handleClick = async () => {
        const response = await fetch("/api/plants/" + plant._id, {
          method: "DELETE",
        });
        const json = await response.json();
    
        if (response.ok) {
          dispatch({ type: "DELETE_PLANT", payload: json });
        }
      };
      const updatePlant = async (e) => {
        e.preventDefault()
        plant.nextWaterDate = newWaterDate
    
        const response = await fetch("api/plants/" + plant._id, {
          method: "PATCH",
          body: JSON.stringify(plant),
          headers: {
            'Content-Type': 'application/json'
          }
        })
        const json = await response.json()
    
        if(response.ok) {
          dispatch({ type: "UPDATE_PLANT", payload: json })
        }
        console.log('updated')
        setWatered(false)
      }
      return (
        <div className="plant-details">
          <h4>{plant.plantName}</h4>
          <p>{plant.quickInfo}</p>
          <p>
            {formatDistanceToNow(new Date(plant.createdAt), { addSuffix: true })}
          </p>
          <span onClick={handleClick}>delete</span>
          <div>
            <p>next water date: {plant.nextWaterDate}</p>
            <input onChange={(e) => setNewWaterDate(e.target.value)}/>
            <button onClick={updatePlant}>update</button>
            <input value={watered} type="checkbox" id="toWater" onChange={() => setWatered(true)}/>
            <label  for="toWater">watered</label>
            {watered && <CalendarComponent updatePlant={updatePlant} setNextWaterDate={setNewWaterDate}/>}
          </div>
          
        </div>
      );
    };
    export default PlantDetails;

Context which wraps my

import { createContext, useReducer } from 'react'

export const PlantsContext = createContext()

export const plantsReducer = (state, action) => {
    switch(action.type) {
        case 'SET_PLANTS':
            return { 
                plants: action.payload 
            }
        case 'CREATE_PLANT':
            return {
                plants: [action.payload, ...state.plants]
            }
        case 'DELETE_PLANT':
            return {
                plants: state.plants.filter((p) => p._id !== action.payload._id)
            }
        case 'UPDATE_PLANT':
            return {
                plants: state.plants.map((p) => p._id === action.payload._id ? action.payload : p )
            }
        default:
            return state
    }
}

export const PlantsContextProvider = ({ children }) => {
    const [state, dispatch] = useReducer(plantsReducer, {
        plants: null
    })

    return (
        <PlantsContext.Provider value={{...state, dispatch}}>
            { children }
        </PlantsContext.Provider>
    )
}

My plantController (update)

const updatePlant = async (req, res) => {
    const { id } = req.params
    if(!mongoose.Types.ObjectId.isValid(id)) {
        return res.status(404).json({ error: "No plant" })
    }

    const plant = await Plant.findByIdAndUpdate({ _id: id }, {
        ...req.body
    })

    if (!plant) {
        return res.status(400).json({ error: "No plant" })
    }
    res.status(200)
    .json(plant)
}

Home component

import { useEffect } from "react";
import PlantDetails from "../components/PlantDetails";
import PlantForm from "../components/PlantForm";
import CalendarComponent from "../components/CalendarComponent";
import { usePlantsContext } from "../hooks/usePlantsContext";
const Home = () => {
  const { plants, dispatch } = usePlantsContext();

  useEffect(() => {
    const fetchPlants = async () => {
      console.log("called");
      // ONLY FOR DEVELOPMENT!
      const response = await fetch("/api/plants");
      const json = await response.json();
      if (response.ok) {
        dispatch({ type: "SET_PLANTS", payload: json });
      }
    };
    fetchPlants();
  }, [dispatch]);
  return (
    <div className="home">
      <div className="plants">
        {plants &&
          plants.map((plant) => <PlantDetails key={plant._id} plant={plant} />)}
      </div>
      <PlantForm />
    </div>
  );
};
export default Home;

Any help would be greatly appreciated.

fluffy-lionz
  • 81
  • 2
  • 12

1 Answers1

0

My patch requests were going through smoothly but my state would not update until I reloaded my page. It was not returning the document after the update was applied.

https://mongoosejs.com/docs/tutorials/findoneandupdate.html#:~:text=%3B%20//%2059-,You,-should%20set%20the

fluffy-lionz
  • 81
  • 2
  • 12