Home > Net >  I tried to pass a function using the React useContext hook but it didn't work, am I doing somet
I tried to pass a function using the React useContext hook but it didn't work, am I doing somet

Time:11-13

I tried to pass a function from the App component to another one, but it says that the function is not defined (in the child component), pretty sure I'm doing something wrong like calling the function in a wrong way but I couldn't figure it out since most answers online were using Class based components

App.js

function App() {
    const API_URL = "https://course-api.com/react-tours-project";
    const [loading, setLoading] = useState(true);
    const [data, setData] = useState([]);

    async function getData() {
        const response = await fetch(API_URL);
        const data = await response.json();
        setData(data);
        setLoading(false);
    }

    useEffect(() => {
        getData();
    }, []);

    const removeItemContext = React.createContext();

    function removeItem(itemId) {
        const newData = data.filter((object) => object.id !== itemId);
        setData(newData);
    }

    if (loading) {
        return (
            <main>
                <Loading />
            </main>
        );
    }

    return (
        <main>
            <removeItemContext.Provider value={removeItem}>
                <Tours data={data} />
            </removeItemContext.Provider>
        </main>
    );
}

export default App;

Tour.js (which is a grandchild)

import React, { useContext } from "react";
import removeItemContext from "./App";
function Tour(data) {
    const { id, name, info, image, price } = data;
    const deleteButton = useContext(removeItemContext);
    return (
        <article>
            <img src={image} alt={name} />
            <h2>{name}</h2>
            <span>{price}</span>
            <p>{info}</p>
            <button
                onClick={() => {
                    removeItem(id);
                }}
            >
                Not interested
            </button>
        </article>
    );
}

export default Tour;

CodePudding user response:

Context creation should be outside your App component: it should occurs only once, not on each rendering (that's the difference with a hook for example ;) )

Something like that:

const removeItemContext = React.createContext();

function App() {
    // ...

    return (
        <main>
            <removeItemContext.Provider value={removeItem}>
                <Tours data={data} />
            </removeItemContext.Provider>
        </main>
    );
}

export default App;

A full implementation would declare the context in a dedicated file to be imported both in App and Tour:

// removeItemContext.js

const removeItemContext = React.createContext();

export default removeItemContext;

// App.js

import removeItemContext from "./removeItemContext.js";

function App() {
    // ...

    return (
        <main>
            <removeItemContext.Provider value={removeItem}>
                <Tours data={data} />
            </removeItemContext.Provider>
        </main>
    );
}

export default App;

// Tour.js

import removeItemContext from "./removeItemContext.js";

function Tour(data) {
    // ...

    const deleteButton = useContext(removeItemContext);

    // ...
}

CodePudding user response:

The data you are referencing in your Tour.js component is actually the props variable that React passes by default. So, you need to destructure the object first. And also destructure the removeItem function from the context.

function Tour({data}) {
    const { id, name, info, image, price } = data;
    const { removeItem } = useContext(removeItemContext);
}
  • Related