0

I am trying to put together a MERN stack application and I am currently working on the client-side. React hooks are somewhat new to me and I am currently trying to use them using usePopup from the react-hook-popup library class, but the values won't update and I'm not sure why?

The two lines of relevant code from below I am particularly having trouble updating are:

const [newChore, setNewChore] = useState("") const [newChoreIndex, setNewChoreIndex] = useState(-1) 

EDIT1: So I have noticed if I setState outside of the popup hook, state will update, which I do for the 'newChoreIndex' hook. Is there something I need to be able to use these hook variables with the popup?

EDIT2: I have repo's to both client-side and server-side which I can share if that makes things easier. After cloning, just run npm i, and then npm start for both applications.

server-side: https://github.com/halsheik/HouseholdHomiesBackend.git client-side: https://github.com/halsheik/HouseholdHomiesFrontend.git

import React, { useState, useEffect } from "react"; import { usePopup } from 'react-hook-popup'; import Axios from "axios"; import "../../stylesheets/modal.css"; import "../../stylesheets/homepage.css"; function HomePage() { const [user, setUser] = useState(null); const [group, setGroup] = useState(null); const [newChore, setNewChore] = useState("") const [newChoreIndex, setNewChoreIndex] = useState(-1) const [showPopup, hidePopup] = usePopup('popup', ({ message, handleClose }) => ( <div className="modal"> <div className="modalInner"> <button className="modalClose" onClick={handleClose}> X </button> <div className="modalInner2"> <p className="modalHeading">Previous Chore(s)</p> <p className="modalChore">{message}</p> <p className="modalHeading">New Chore {newChoreIndex}</p> <input className="newChoreInput" placeholder="New Chore" onChange={(e) => {setNewChore(e.target.value)}} /> <button className="modalSubmit" onClick={() => { updateChore() hidePopup() }}> Update Chore </button> </div> </div> </div> )); useEffect(() => { Axios({ method: "GET", withCredentials: true, url: "http://localhost:4000/", }).then((res) => { setUser(res.data); if(!res.data) { window.location.href = "/login"; } }); Axios({ method: "GET", withCredentials: true, url: "http://localhost:4000/group", }).then((res) => { setGroup(res.data); console.log(res); }); }, []) useEffect(() => { console.log(newChore) }, [newChore]) useEffect(() => { console.log(newChoreIndex) }, [newChoreIndex]) const updateChore = () => { }; return ( <div className="mainContainer"> {user ? ( <div className="contentContainer"> <p className="homepageHeading">Welcome resident's of {user.address}</p> {!group ? ( <div className="groupNotSetupContainer"> <p className="groupNotSetup">Household has not been setup</p> <a href="/createGroup" className="groupNotSetupButtonContainer"><button className="groupNotSetupButton">Setup Household</button></a> </div> ) : ( <div className="groupContent"> <div className="groupContentCol"> <p className="groupContentColHeading">Household Members</p> {group.members.map((item, index) => { return ( <div key={index} className="groupContentColMember"> <p className="groupContentColItemText">{item["name"]}</p> </div> ) } )} </div> <div className="groupContentCol"> <p className="groupContentColHeading">Chores</p> {group.chores.map((item, index) => { var member = group.head + parseInt(index) if(member >= group.members.length) { member = 0 } return ( <div key={index} className="groupContentColChore"> {item === "organizer" ? ( <div className="groupContentColChoreInner"> <p className="groupContentColItemText">{item}</p> <p className="groupContentColItemText assignedChore">{group.members[member]["name"]}</p> </div> ) : ( <div className="groupContentColChoreInner"> <p className="groupContentColItemText killCurves">{item}</p> <p className="groupContentColItemText assignedChore">{group.members[member]["name"]}</p> </div>)} {item !== "organizer" && <p href="#" className="groupContentColChoreEdit" onClick={() => { setNewChoreIndex(index) showPopup(item) }}>Edit</p> } </div> ) } )} </div> </div> )} </div> ) : ( // should not enter here <div> <h1>Welcome to household homies, please login</h1> <p><a href="/login">login</a></p> <p><a href="/register">register</a></p> </div> )} </div> ); } export default HomePage; 

enter image description here

EDIT 4:

Popup hook

const [showPopup, hidePopup] = usePopup('popup', ({ message, chore, handleClose }) => ( <div className="modal"> <div className="modalInner"> <button className="modalClose" onClick={handleClose}> X </button> <div className="modalInner2"> <p className="modalHeading">Previous Chore(s)</p> <p className="modalChore">{message}</p> <p className="modalHeading">New Chore {chore}</p> <input className="newChoreInput" placeholder="New Chore" onChange={(e) => {setNewChore(e.target.value)}} /> <button className="modalSubmit" onClick={() => { console.log(chore) updateChore() hidePopup() }}> Update Chore </button> </div> </div> </div> )); 

hook call

showPopup(item, newChore) 

EDIT 5:

Before clicking 'edit' to open popup: enter image description here

After opening popup (notice a blank and -1 in the console indicating the newChore and newChoreIndex passed in)

enter image description here

After typing in input field of popup (notice the console with 5 blanks since I console.logged the newChore value in the popup which still has no value)

enter image description here

After closing the popup and reopening (notice the values of newChore and newChoreIndex have updated)

enter image description here

1 Answer 1

1

I can't comment because I've only just made an account

That being said I can update this answer if you can provide a bit more information :)

Where are you checking for the result of the new chore being set? I can see in the code you posted that there's the new chore index being logged in the updateChore function but not the newChore itself. Have you tried logging in another useEffect? like...

useEffect(() => { console.log(newChore); }, [newChore]); 

* UPDATE

Seeing as you're only using newChore inside the popup, you could try moving the useState call for newChore inside of the popup body then passing it to the updateChore function like this

const [showPopup, hidePopup] = usePopup('popup', ({ message, handleClose }) => { const [newChore, setNewChore] = useState(""); useEffect(() => { console.log(newChore); }, [newChore]); return ( <div className="modal"> <div className="modalInner"> <button className="modalClose" onClick={handleClose}> X </button> <div className="modalInner2"> <p className="modalHeading">Previous Chore(s)</p> <p className="modalChore">{message}</p> <p className="modalHeading">New Chore {newChoreIndex}</p> <input className="newChoreInput" placeholder="New Chore" onChange={(e) => {setNewChore(e.target.value)}} /> <button className="modalSubmit" onClick={() => { updateChore(newChore) hidePopup() }}> Update Chore </button> </div> </div> </div> ) }); 

This will stop the useEffect on setChore working outside of the popup though as it's not in scope, so you'll probably have to move that into the popup as well to see if it's updating on change.

Sign up to request clarification or add additional context in comments.

21 Comments

The log won't change (as far as I'm aware) in the onChange. From what I understand when you call setNewChore react will queue or store that change, run everything else that comes after then re-render the component as the data has changed. When the component re-renders it runs the function component again, so the useState function will be called again and return the updated value for newChore. If you console.log(newChore) somewhere else in the component body it should in theory log when the value changes :) * Sorry took too long to respond and you'd already replied
Try passing the values into showPopup like showPopup({ newChore, newChoreIndex }) then accessing them as message.newChore and message.newChoreIndex
Also, no problem man :)
I'd assume you'd be able to use an object as that dynamic value if it only takes the one value as an argument? If you're already passing in item, could you not pass in an object like { item, newChore } then use { message.item } where you're already using { message }?
Ah good man :) sorry it's taking me too long to reply to these bahaha
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.