Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call useState from another Page?

Bascially whenever I deleted an item in my handleDelete function it would route back to the homePage and I wanted to display a message that says your product succesully deleted for about 5 seconds.

In my index.js I first set message to false. and inside my ProductAttribute whenever I click it the set message will be true and will show the message in Index.js/ in my UI.

my handleDelete function

import React, { useState } from "react";
import { Header, Button, Modal } from "semantic-ui-react";
import axios from "axios";
import baseUrl from "../../utils/baseUrl";
import { useRouter } from "next/router";

function ProductAttributes({ description, _id }) {
    const [modal, setModal] = useState(false);
    const router = useRouter();

async function handleDelete() {
    const url = `${baseUrl}/api/product`;
    const payload = { params: { _id } };
    await axios.delete(url, payload);
    router.push("/");
    setMessage(true);
    setTimeout(function () {
        setMessage(false);
    }, 5000);
}

while in my Index.js. The setMessage in my useState isn't getting called from ProductAttributes file.

import React, { useEffect, useState } from "react";
import axios from "axios";
import ProductList from "../components/Index/ProductList";
import baseUrl from "../utils/baseUrl";
import { Message, Container } from "semantic-ui-react";

function Home({ products }) {
    const [message, setMessage] = useState(false);
    return (
        <>
            <Container>
                {message ? (
                    <Message
                        deleted
                        icon="checked"
                        color="red"
                        content=" Product Successfully Deleted"
                    />
                ) : (
                    ""
                )}
            </Container>
            <ProductList products={products}></ProductList>
        </>
    );
}

How can I make this setMessagebe callable in ProductAttributes? am I doing it right with the Parent to Child Relation or should I bring the useState in the child to parent?

like image 940
Grizzly Bear Avatar asked Oct 27 '22 19:10

Grizzly Bear


2 Answers

You can create an handler in the Home Component like this

const handleSetMessage = (message) => {
    setMessage(message)
}

this handler will be responsible of updating the value of message state in the Home component. and this methode you can pass it as props to ProductList component which will also pass it down to ProductAttribute. This will force you to pass props till the lowest level in your APP where you need to call that method.

Or you can take advantage of Context API which will allow you to have access to that method without passing it down as props.

const MessageContext = React.createContext("");

And in the Home component you use that Context like this

function Home () {
    const [message, setMessage] = useState('');
    
    const handleSetMessage = () => {
        setMessage(true)
    }
    return <MessageContext.Provider> value={{setMessage: handleSetMessage}}>
         // The code which render the component child goes here.
    </MessageContext.Provider>
}

After that in your ProductAttribute Component you access to that setMessage function like this

import React, { useContext} from 'react';


const ProductAttribute = (props) => {
    const { setMessage } = useContext(MessageContext);
    
    const handleDelete = async () => {
        // Here you call the setMessage function which will update state in the `Home` Component
        setMessage();
    } 

    return <div>

    </div>
}
like image 59
Yves Kipondo Avatar answered Nov 15 '22 12:11

Yves Kipondo


How can I make this setMessagebe callable in ProductAttributes?

A good practice would encompass you creating a handler function which delegates to the setState function and passing the reference of this function to ProductAttributes as props.

this is an example:

const [counter, setCounter] = useState(0);
const handleIncrementCounter = () => setCounter(counter + 1);
<ChildComponent handleIncrementCounter ={handleIncrementCounter }/>

then in ChildComponent..

function ChildComponent(props) {
   return (
      <button onClick={props.handleIncrementCounter}/>
   );
}
like image 20
pixelatedCat Avatar answered Nov 15 '22 11:11

pixelatedCat