6

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?

Grizzly Bear
  • 318
  • 4
  • 18

3 Answers3

2

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>
}
Yves Kipondo
  • 5,289
  • 1
  • 18
  • 31
1

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}/>
   );
}
pixelatedCat
  • 312
  • 5
  • 17
0

Once you show you a message, wait for 5sec to close the message and redirect back to the home directory. just place the route.push('/') inside setTimeout so it will wait for 5sec to be redirected.

async function handleDelete() {
    const url = `${baseUrl}/api/product`;
    const payload = { params: { _id } };
    await axios.delete(url, payload);
    setMessage(true);
    setTimeout(function () {
        router.push("/");
        setMessage(false);
    }, 5000);
}
Ericgit
  • 6,089
  • 2
  • 42
  • 53
  • It should route to the index first router.push("/") and then the message will display. and the setMessage says it is not a function. How can I call the setMessage from Index.js to ProductAttributes.js? . – Grizzly Bear Jul 20 '20 at 08:05
  • You should pass `setMessage` props to `ProductAttributes` component, then it would work! – Ericgit Jul 20 '20 at 08:15
  • function ProductAttributes({ description, _id, setMessage }) I passed it and it says's setMessage is not a function – Grizzly Bear Jul 20 '20 at 08:21
  • https://github.com/GrizzlyBear-Michaelangelo/Ecommerce.git here is it. sorry for the late reply. – Grizzly Bear Sep 04 '20 at 08:20