blank screen after wrapping App component with react-context - javascript

I am writing the context API and everything is working fine but when I wrapped the App component with the context screen became blank
Code of contex
import { useState } from "react";
import { createContext, useContext } from "react";
const chatContext = createContext();
const ChatContext = ({ childern }) => {
const [user, setuser] = useState();
return (
<chatContext.Provider value={{ user, setuser }}>
{childern}
</chatContext.Provider>
);
};
export const ChatState = () => {
return useContext(chatContext);
};
export default ChatContext;
code of index.js before wrapping contex
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById("root")
);
**code after wrapping context api **
import ChatContext from "./Context/ChatContext";
ReactDOM.render(
<ChatContext>
<Router>
<App />
</Router>
</ChatContext>,
document.getElementById("root")
);
but the screen becomes blank anyone how can help me.
I tried to solve this problem but can not able to do so. plz anyone how can help me will be appricated

i think you just misspelled children you wrote childern and if you fix how you wrote it the problem will be solved
const ChatContext = ({ *childern* children }) => {
const [user, setuser] = useState();
return (
<chatContext.Provider value={{ user, setuser }}>
{*childern* children}
</chatContext.Provider>
);
};
export const ChatState = () => {
return useContext(chatContext);
};
export default ChatContext;

Related

Changing the state of a context within an if-else in JavaScript

I tried making a global state by using a Context and have the following for my AuthProvider.js file
import { createContext, useState } from "react";
const AuthContext = createContext({});
export const AuthProvider = ({ children }) => {
const [auth, setAuth] = useState({});
return (
<AuthContext.Provider value={{ auth, setAuth }}>
{children}
</AuthContext.Provider>
)
}
export default AuthContext;
I want to be able to change its boolean state within an if-else instead of a button with an onCLick event in the tutorial but it shows an error in the console: setAuth is not a function
function Home() {
const setAuth = useContext(AuthProvider);
const [usernameReg, setUsernameReg] = useState("");
const [passwordReg, setPasswordReg] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loginStatus, setloginStatus] = useState("");
const uLogin = document.getElementById('userLogin');
const pLogin = document.getElementById('passwordLogin');
const register = () => {
if (usernameReg === "" || passwordReg === ""){
alert("Fields can't be blank");
return;
}
Axios.post('http://localhost:3001/register', {
username: usernameReg,
password: passwordReg,
}).then((response) => {
console.log(response);
});
}
const login = () => {
Axios.post('http://localhost:3001/login', {
username: username,
password: password,
}).then((response) => {
if (response.data.message){
setloginStatus(response.data.message);
alert(response.data.message);
}
else{
setloginStatus(response.data[0].username);
setAuth(true); <====================================== here
window.location.href = "/map";
}
console.log(response.data);
});
}
return (
<div className="Home">
<h1>Register</h1>
<label>Username: </label>
<input type="text"
onChange={(e) => {
setUsernameReg(e.target.value)
}}/>
<label><p></p>Password: </label>
<input type="text"
onChange={(e)=> {
setPasswordReg(e.target.value)
}}/>
<p></p>
<button onClick={register}> Register </button>
<h1>--------------------------------------------------------</h1>
{/*<form id="loginForm">*/}
<h1>Log In</h1>
<input id="userLogin" type="text" placeholder="Username"
onChange={(e) => {
setUsername(e.target.value)
}}
/>
<p></p>
<input id="passwordLogin" type="password" placeholder="Password"
onChange={(e) => {
setPassword(e.target.value)
}}
/>
<p></p>
<button onClick={login}> Log In </button>
{/*</form>*/}
<h1>{loginStatus}</h1>
</div>
)
}
my App.js is below
import React, { useState } from "react";
import { BrowserRouter,Route, Routes} from 'react-router-dom';
import './App.css';
import Home from "./Pages/Home";
import MapPage from "./Pages/MapPage.js";
import ProtectedRoutes from "./ProtectedRoutes";
import { AuthProvider } from "./components/AuthProvider"
function App() {
const [auth, setAuth ] = useState(false);
//const [auth, setAuth] = useState(false);
return (
<BrowserRouter>
<Routes element ={<AuthProvider />} value={{auth, setAuth}}>
<Route element ={<ProtectedRoutes />}>
<Route element={<MapPage />} path="/map" exact/>
</Route>
<Route path="/" element={<Home />}/>
</Routes>
</BrowserRouter>
);
}
export default App;
index.js below
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { AuthProvider } from './components/AuthProvider'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<AuthProvider>
<App />
</AuthProvider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bitly/CRA-vitals
reportWebVitals();
I'm very new to JavaScript and I've only been following along tutorials for the functions or features I need for the project. Is there a way for this?
I'm also guessing that the code for the context file is overkill for a simple Boolean state.
You probably want to check the context docs again, and try to understand how and why you set them up, and how to access them. You tried accessing the context by passing the provider as a param to the useContext hook. This is wrong, you need to pass the Context itself. You also called the return from the context setAuth, but the return is the context itself. I urge you to read the documentation thourougly. However, this is probably what you wanted:
type AuthContextType = {
auth: boolean;
setAuth: Dispatch<SetStateAction<boolean>>;
};
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
const [auth, setAuth] = useState(false);
return (
<AuthContext.Provider value={{ auth, setAuth }}>
{children}
</AuthContext.Provider>
);
};
const useAuthContext = () => {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("No AuthContext Provider found");
return ctx // as AuthContextType<...> if you need the context to be generic and to infer generics.
};
function Home() {
const { auth, setAuth } = useAuthContext();
...
}

React passing props to other components

Hello I am having trouble passing props between components. I can't share the exact code so I made a simplified version. I am not getting any console errors, though login is obviously 'undefined' Any insight is appreciated!
App.js
import React, { useState } from "react";
function App() {
const [login, setLogin] = useState('Jpm91297');
const changeState = () => {
const newLogin = document.getElementById('loginData').value;
setLogin(newLogin);
}
return (
<>
<h1>Fancy API Call!!!</h1>
<form onSubmit={() => changeState()}>
<input type='text' id='loginData'></input>
<button>Submit</button>
</form>
</>
);
}
export default App;
Api.Js
import React, {useEffect, useState} from "react";
const Api = ( { login } ) => {
const [data, setData] = useState(null);
useEffect(() => {
fetch(`https://api.github.com/users/${login}`)
.then((res) => res.json())
.then(setData);
}, []);
if (data) {
return <div>{JSON.stringify(data)}</div>
}
return <div>No data Avail</div>
}
export default Api;
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Api from './api'
ReactDOM.render(
<>
<App />
<Api />
</>,
document.getElementById('root')
);
You are not preventing the default form action from occurring. This reloads the app.
You should lift the login state to the common parent of App and Api so it can be passed down as a prop. See Lifting State Up.
Example:
index.js
Move the login state to a parent component so that it can be passed down as props to the children components that care about it.
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Api from './api';
const Root = () => {
const [login, setLogin] = useState('Jpm91297');
return (
<>
<App setLogin={setLogin} />
<Api login={login} />
</>
);
};
ReactDOM.render(
<Root />,
document.getElementById('root')
);
App
Pass the changeState callback directly as the form element's onSubmit handler and prevent the default action. Access the form field from the onSubmit event object.
function App({ setLogin }) {
const changeState = (event) => {
event.preventDefault();
const newLogin = event.target.loginData.value;
setLogin(newLogin);
}
return (
<>
<h1>Fancy API Call!!!</h1>
<form onSubmit={changeState}>
<input type='text' id='loginData'></input>
<button type="submit">Submit</button>
</form>
</>
);
}
Api
const Api = ({ login }) => {
const [data, setData] = useState(null);
useEffect(() => {
fetch(`https://api.github.com/users/${login}`)
.then((res) => res.json())
.then(setData);
}, [login]); // <-- add login dependency so fetch is made when login changes
if (data) {
return <div>{JSON.stringify(data)}</div>;
}
return <div>No data Avail</div>;
};

Why does optional chaining allows rendering when fetching data through useEffect in an app that uses context?

I'm new to the webdev world and want to learn ReactJS. I followed a tutorial I found on YouTube made by Traversy where he makes a task tracker and now I want to make some changes to it to learn and practice some more.
I want to use context for the appointments (originally named tasks in the tutorial), add a calendar with react-calendar and use react-router-dom.
I got stuck for a while trying to make the list render, because it only rendered "empty". Later on found this post with a similar issue to mine: Only run a useEffect fetch after first useEffect fetch has fired and setUser in context
I changed bits of my code based on that post and now it does render the appointment list, but I don't know why it didn't work before and I'm unsure on why it does work now. I don't even know if I'm using context correctly or just prop-drilling. Help would be greatly appreciated. Thank you.
Also, sorry if my code is a mess, I'm new at this.
App.js
import { createContext, useState, useEffect } from "react";
import Dashboard from "./views/Dashboard";
import './App.css';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";
import AddAppointmentForm from "./views/AddAppointmentForm";
export const AppContext = createContext();
export const AppUpdateContext = createContext();
function App() {
const [appointments, setAppointments] = useState([])
const updateAppointments = (apptList) => {
setAppointments(apptList)
}
return (
<AppContext.Provider value={ appointments }>
<AppUpdateContext.Provider value={ updateAppointments }>
<Router>
<Routes>
<Route path="/" element={<Dashboard appointments={appointments} />} />
{/* <Route path="/add" element={<AddAppointmentForm />} /> TBA */}
</Routes>
</Router>
</AppUpdateContext.Provider>
</AppContext.Provider>
);
}
export default App;
Dashboard.js
import { useEffect, useContext} from "react";
import { AppContext } from "../App";
import { AppUpdateContext } from "../App";
import AppointmentList from "../components/AppointmentList";
import Header from "../components/Header";
// function Dashboard() { // this is how it used to be
function Dashboard(props) {
const appointments = useContext(AppContext)
const setAppointments = useContext(AppUpdateContext)
const fetchAppointmentList = async () => {
const res = await fetch("http://localhost:5000/appointments");
const data = await res.json();
return data;
}
useEffect(() => {
const getAppointments = async () => {
const appointmentsFromServer = await fetchAppointmentList();
setAppointments(appointmentsFromServer);
}
getAppointments();
console.log("ñññññ",appointments)
}, []);
console.log("aagh",appointments)
return (
<div style={dashboardStyle}>
<Header />
{/* {appointments.lenght>0 ? (<AppointmentList />) : <p>empty</p>} this is how it used to be */}
<AppointmentList appointments={props?.appointments}/>
</div>
);
}
const dashboardStyle = {
maxWidth: "31.25rem",
overflow: "auto",
minHeight: "18.75rem",
border: "1px solid steelblue",
margin: "1.875rem auto",
padding: ".5rem",
boxSizing: "border-box",
}
export default Dashboard;
AppointmentList.js
import Appointment from "./Appointment";
import { AppContext } from "../App";
import { useContext } from "react";
function AppointmentList({ appointments }) {
// function AppointmentList() { // this is how it used to be
// const { appointments, setAppointments } = useContext(AppContext)
console.log("appList",appointments) // this is how it used to be
return (
<>
{
appointments.map(appt => (
<Appointment key={appt.id} appointment={appt} />
))
}
</>
);
}
export default AppointmentList;
Why does optional chaining allows rendering when fetching data through
useEffect in an app that uses context?
<AppointmentList appointments={props?.appointments}/>
It allows rendering by preventing accidental accesses into potentially null or undefined objects. The only way props could be undefined though is if you just simply don't declare it, i.e. const Dashboard = () => {.... vs const Dashboard = (props) => {.....
You are drilling the appointments state through props. AppointmentList can use the AppContext context to access the appointments state, while Dashboard can use the AppUpdateContext context to update the appointments state.
App
function App() {
const [appointments, setAppointments] = useState([]);
const updateAppointments = (apptList) => {
setAppointments(apptList);
};
return (
<AppContext.Provider value={{ appointments }}> // <-- need object here
<AppUpdateContext.Provider value={{ updateAppointments }}> // <-- and here
<Router>
<Routes>
<Route path="/" element={<Dashboard />} /> // <-- don't pass props
</Routes>
</Router>
</AppUpdateContext.Provider>
</AppContext.Provider>
);
}
Dashboard
function Dashboard() { // <-- no props
const { updateAppointments } = useContext(AppUpdateContext); // <-- access from context
const fetchAppointmentList = async () => {
const res = await fetch("http://localhost:5000/appointments");
const data = await res.json();
return data;
};
useEffect(() => {
const getAppointments = async () => {
const appointmentsFromServer = await fetchAppointmentList();
updateAppointments(appointmentsFromServer);
}
getAppointments();
}, []);
return (
<div style={dashboardStyle}>
<Header />
<AppointmentList /> // <-- don't pass props
</div>
);
}
AppointmentList
function AppointmentList() { // <-- no props
const { appointments } = useContext(AppContext); // <-- access from context
return appointments.map(appt => (
<Appointment key={appt.id} appointment={appt} />
));
}

How to fix the Rendered more hooks than during the previous render using react hook

index.tsx
import useUser from '#services/users';
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
function App() {
const { t } = useTranslation();
const { getAll } = useUser();
const [ rowData, setRowData ] = useState([]);
useEffect(() => {
let ignore = false;
(async function setAllData() {
let response = await getAll({ length: 9999 });
})()
if (!ignore) {
setRowData(response['data']['data']);
}
})()
return () => {
ignore = true;
}
}, [])
return (
<>
<button>{t('create')}</button>
{
rowData.map((item, index) => (
<div key={index}>
{item.firstName}<br/>
</div>
))
}
</>
)
}
export default App;
user.tsx
export default function useUser() {
const creds = useCredentials();
Axios.defaults.baseURL = serverConfig[creds.server].api;
return {
getAll: (params?: object) => Axios.get(API_URL + (params ? getQueryParams(params) : ''))
}
}
I'm having trouble when I added the react-i18next which is the useTranslation. The error message is Rendered more hooks than during the previous render. when added the translation. How do I fix on it?
I had the same issue with useTranslation.
For me the cause was wrapping the i18next init script in a function calling that inside App.tsx instead of just exporting i18n and importing it directly inside index.tsx
So NOT:
App.tsx
import initI18n from './i18n.ts'
const App = () => {
initI18n()
return <div>Party</div>
}
BUT THIS WORKED
index.tsx
import './i18n.ts'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);

onClick doesn't fire event React.js

I'm trying to toggle element by clicking on button, however it doesn't do anything. Also note that code is simplified as I didn't want to copy whole app, I just included parts I thought are important. Here is code:
Navbar.js ..Here I try to invoke the function it comes from context.js file where I setup my contextAPI
import { useGlobalContext } from "./context";
const { openSidebar, openSubmenu, closeSubmenu } = useGlobalContext();
<button className="btn toggle-btn" onClick={openSidebar}>
context.js
const AppContext = React.createContext();
const AppProvider = ({ children }) => {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const openSidebar = () => {
console.log("test")
setIsSidebarOpen(true);
};
return (
<AppContext.Provider value={(isSidebarOpen, openSidebar, closeSidebar)}>
{children}
</AppContext.Provider>
);
}
export const useGlobalContext = () => {
return useContext(AppContext);
};
export { AppContext, AppProvider };
App.js
document.addEventListener("click", (e) => {
console.log(e);
console.log(e.target);
});
index.js
import App from "./App";
import { AppProvider } from "./context";
ReactDOM.render(
<React.StrictMode>
<AppProvider>
<App />
</AppProvider>
</React.StrictMode>,
document.getElementById("root")
);
The event listener from App.js displays correctly event and also event.target which is the button. However I don't get any log to console from context.js where it should log "test", not error, not warning, nothing... onClick is completely ignored.
You will find your answer here
onClick={( )=>{openSidebar( )}}
Okay Ive resolved it, the problem was in parentheses in context.js
here is old code:
return (
<AppContext.Provider value={(isSidebarOpen, openSidebar, closeSidebar)}>
{children}
</AppContext.Provider>
);
here is new one:
return (
<AppContext.Provider value={{ isSidebarOpen, openSidebar, closeSidebar }}>
{children}
</AppContext.Provider>
);
I needed to replace () with {}

Categories

Resources