简体   繁体   中英

How to change a function passed as a prop to React component?

I'm trying to build a reusable SnackBar (little popup displaying info of what just happened) component with optional UNDO action. I would like to use it like this:

Main component

import SnackBar from "./SnackBar";
import { useState } from "react";

const MainComponent({item}) => {
        const [snackBarVisible, setSnackBarVisible] = useState(false);
        const [snackBarMessage, setSnackBarMessage] = useState("");
        const [undoFunction , setUndoFunction ] = useState(null);
        //var undoFunction = null;

        const undoAddToFav = () => {
                //code that removes from favorites the stuff that was just added 
                console.log("removed last added product from favs");
        };

        const undoAddToCart = () => {
                //code that removes from cart the last added product
                console.log("removed last added product from cart");
        }

        const addToCart = (item) => {
                //some code
                setSnackBarMessage("Item added to cart");
                //HELP NEEDED HERE
                //undoFunction = undoAddToCart; // this doesn't work at all (no error messages)
                setUndoFunction(() => undoAddToCart()) // this executes undoAddToCart when addToCart is called and not on button press
                setSnackBarVisible(true);
        }
        const addToFavorites = (item) => {
                //some code
                setSnackBarMessage("Item added to favourites");
                //undoFunction = undoAddToFav ; // <== HELP NEEDED HERE
                //setUndoFunction(() => undoAddToCart()) 
                setSnackBarVisible(true);
        }
        const displaySnackBar = () => {
                setSnackBarMessage("Some info");
                setSnackBarVisible(true);
                //this one has no "undo" button
        }
        //some other stuff
        return (
                //some other stuff that calls the actions above
                <SnackBar snackBarMessage = {snackBarMessage} snackBarVisible = {snackBarVisible) undoFunction = {undoFunction}/>
        );
};

Child component

I'd like this undo action to be optional.

export default const SnackBar = ({snackBarMessage, snackBarVisible, undoFunction}) => {
        //some stuff
        return (
                <>                
                        //some stuff - handle visibility, etc
                        //help needed here as well - how do I display the button only when the function prop is passed?
                        {undoFunction && <button onClick={undoFunction}>UNDO</button>}; //this doesn't work properly
                        <div>{snackBarMessage}</div>;
                </>
        );
};

I've tried useState, useCallback, useMemo, useRef to handle this and nothing seems to work. This is my first cry for help here:)

编辑 gracious-keller-ixbcuk

You must declare undoFunction using useState , ex by default null:

const [undoFunction, setUndoFunction] = useState(null)

And then use setUndoFunction(/* your new function here or null */) .

It didn't work because if you don't use a state, React won't re-render changes.

The problem for your question starts from MainComponent

const [undoFunction , setUndoFunction ] = useState(null);

Since the value of undoFunction is null, the button won't render at all in the child component. I mean this code.

{undoFunction && <button onClick={undoFunction}>UNDO</button>}; //this doesn't work properly

You can change it to something like this. Render the button and execute undoFunction if that's available.

<button
  onClick={() => {
    if (undoFunction) undoFunction();
  }}
>
UNDO
</button>

I have made a simple sandbox for this functionality. I've used an extra button for passing undo functionality. Check the code and see how you can use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM