I am trying to build a simple React App with some CRUD connected to a Rails API. The structure of the project is this:
App.js
-> UserIndex
--> Form
--> User
-> User
I want to send a value (a function) from <App />
to its grandchild (NOT the immediate child) <User />
.
This is <App />
:
import "./App.css";
import User from "./components/User";
import UserIndex from "./components/UserIndex";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { useState, createContext } from "react";
export const UserContext = createContext();
function App() {
const [user, setUser] = useState({});
// function handleShow() {
// console.log("showed!");
// }
const handleShow = "fñalksdjfñdlskfjds";
return (
<div>
<UserContext.Provider value={handleShow}>
<BrowserRouter>
<Routes>
<Route path="/" element={<UserIndex />}></Route>
<Route
path="users/:userId"
element={<User id={1} name={"hey"} email={"there"} />}
/>
</Routes>
</BrowserRouter>
</UserContext.Provider>
</div>
);
}
export default App;
This is <User />
:
import React, { useContext } from "react";
import { Link } from "@mui/material";
import axios from "axios";
import UserContext from "../App";
function User(props) {
const userName = useContext(UserContext);
console.log(userName);
return (
<div className="centerText">
<Link
href={`/users/${props.id}`}
color="inherit"
onClick={props.handleShow}
>
<h4>{props.name}</h4>
<h4>{props.email}</h4>
</Link>
{props.deleteData && <button onClick={props.deleteData}>Delete</button>}
</div>
);
}
export default User;
So I created the Context and provided it in <App />
and consumed it in . But when I console.log(userName);
it returns undefined
.
Am I doing something wrong? Thanks!
CodePudding user response:
<Route
path="users/:userId"
element={<User id={1} name={"hey"} email={"there"} />}
/>
This route has the problem, since there is no provider higher up the tree. When this route renders, <User>
will get undefined
from useContext(UserContext)
. The other route should be fine.
To fix this route, make sure your provider is higher up the component tree. For example, a single provider surrounding all of the routes:
return (
<UserContext.Provider value={handleShow}>
<div>
<BrowserRouter>
<Routes>
<Route
path="/"
element={<UserIndex />}
/>
<Route
path="users/:userId"
element={<User id={1} name={"hey"} email={"there"} />}
/>
</Routes>
</BrowserRouter>
</div>
</UserContext.Provider>
)
CodePudding user response:
value = {[handleShow,user,setUser]}
**and catch like this**
const value = useContext(UserContext);
const handleShow = value[0];
const user = value[1];
const setUser = value[2];
CodePudding user response:
import "./App.css";
import User from "./components/User";
import UserIndex from "./components/UserIndex";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { useState, createContext } from "react";
export const UserContext = createContext();
function App() {
const [user, setUser] = useState({});
const handleShow = "testtest";
return (
<div>
<UserContext.Provider value={handleShow}>
<BrowserRouter>
<Routes>
<Route
path="/"
element={<UserIndex />}
></Route>
<Route
path="users/:userId"
element={<User id={1} name={"hey"} email={"there"} />}
/>
</Routes>
</BrowserRouter>
</UserContext.Provider>
</div>
);
}
export default App;