Context is not available right after page refresh in React - reactjs

There's WarriorPage component which use context where is data I want to render. After page refresh, firstly I got an empty array from the context and only after a while I got array with my data. That causes error because I'm destructuring object from that array(which is empty in the start). Any sugestions?
WarriorPage
import React, { useContext } from 'react';
import { useParams } from 'react-router-dom';
import AllWarriorsContext from '../../contexts/AllWariorsContext';
export default function WarriorPage() {
let { identy } = useParams();
const { warriorsData } = useContext(AllWarriorsContext);
const {number, name, skill, description} = warriorsData[identy]; // got undefined here after page reload
return(...);
}
In Parent component
import React, { useEffect, useState, useContext } from 'react';
import AllWarriorsContext from '../../contexts/AllWariorsContext';
import WarriorPage from '../WarriorPage/WarriorPage';
export default function Parent() {
const [myWarriorsListContext, setMyWarriorsListContext] = useState([]);
useEffect( () => {
setMyWarriorsListContext(JSON.parse(localStorage.getItem('myWarriorsList')) || []);
},[]);
return(
<AllWarriorsContext.Provider value={{
warriorsData: allWarriorsData
}}>
<WarriorPage />
</AllWarriorsContext>
);
}

Related

Why the context provider doesn't pass props with useContext inside children as function

I'm trying to access the context props using useContext inside a children as function but the props are always the default
import React, { createContext, useContext } from "react";
const Context = createContext(undefined);
export default function Component() {
return (
<Context.Provider value={{ variable: 123 }}>
{(() => {
const context_value = useContext(Context);
console.log(context_value);
return <></>;
})()}
</Context.Provider>
);
}
Output:
undefined
I know I can use the Context.Consumer but in my real case is different because I'm creating a hook in another file to call useContext(context) instead of exporting Context
You can only use hooks (like useContext) at the top-level of function components (or in custom hooks), but not in the place where you're using it. Try to put a child component inside the provider and to put the useContext inside that child component.
this works for me, hope this will helpful to you also.
//AppContext.js
import { createContext } from 'react';
export const AppContext = createContext(null);
//Authenticated.js
import { useState } from 'react';
import { AppContext } from '#/src/AppContext';
export default function Authenticated()
{
const [message, setMessage] = useState('message');
return (
<AppContext.Provider value={{ message, setMessage }}>
<FlashMessage />
</AppContext.Provider>
);
}
//FlashMessage.js
import { useContext, useState} from 'react';
import { AppContext } from '#/src/AppContext';
const export default FlashMessage = () =>
{
const { message } = useContext(AppContext);
return (
<div>{message}</div>
);
}

React.js - passing functions between components using Context API - not working

I am trying to pass a function between two components but even though I do not have any errors, the function that I am passing wont show or to be precise it is not working. I have two files and one of them is creating a context while the other is using it (obviously). Now, they are not shown in App.js (which is rendered in index.js, usual stuff) they are in the seperate folder. I am using React Router to show one the pages (News.js).
Here are the files:
NewsContext.js
import React, { useContext, createContext, useState, useEffect } from "react";
export const newsK = React.createContext();
export const NewsContext = (props) => {
const working = () => {
console.log("it is working");
};
return <newsK.Provider value={working}>{props.children}</newsK.Provider>;
};
export default NewsContext;
News.js
import React, { useContext, useState, useEffect } from "react";
import { newsK } from "./NewsContext";
import { NewsContext } from "./NewsContext";
const News = () => {
const data = useContext(newsK);
return (
<NewsContext>
<div>
<button onClick={data}></button>
</div>
</NewsContext>
);
};
export default News;
When i pressed the button, it wont do anything. Any tips?
You're trying to use context outside the NewsContext component
The solution for this will be to create a component that will call useContext inside NewsContext.
I.e.
const WrappedButton = () => {
const data = useContext(newsK)
return <button onClick={data} />
}
And then put it inside the NewsContext:
<NewsContext>
<div>
<WrappedButton />
</div>
</NewsContext>

Merging two objects with useContext and state?

So i have this problem where it doesn't merge the two objects since refsContext is empty when useEffect gets called after render. It ends with only one of the refs in the object. useEffect(() => {setRef(something)}, [ref]); results in an infinite empty object loop. Did i miss something?
refs.context.jsx
import { createContext } from "react";
const refsContext = createContext({});
export default refsContext;
Same code over multiple files
/** #jsx jsx */
import React, { useContext, useEffect, useRef } from "react";
import refsContext from "../../context/refs.context";
const StackoverflowExample= () => {
const projectsRef = useRef(null);
const [ref, setRef] = useContext(refsContext);
useEffect(() => {
setRef({ ...ref, projects: projectsRef.current });
}, []);
return (
<section ref={projectsRef}></section>
);
};
export default StackoverflowExample;
App.jsx
import React, { useState, useEffect } from "react";
import { render } from "react-dom";
import Pages from "./Pages";
import { BrowserRouter } from "react-router-dom";
import refsContext from "./context/refs.context";
const App = () => {
//Default Contexts
const refsHook = useState({});
console.log(refsHook[0]);
//All my wrappers/providers for my App
return (
<refsContext.Provider value={refsHook}>
<BrowserRouter>
<Pages/>
</BrowserRouter>
</refsContext.Provider>
);
};
render(<App />, document.getElementById("root"));

createContext using a dynamic object

1. Static object
To create context based on a static object, I use this code:
import React, { createContext } from 'react';
const user = {uid: '27384nfaskjnb2i4uf'};
const UserContext = createContext(user);
export default UserContext;
This code works fine.
2. Dynamic object
But if I need to create context after fetching data, I use this code:
import React, { createContext } from 'react';
const UserContext = () => {
// Let's suppose I fetched data and got user object
const user = {uid: '18937829FJnfmJjoE'};
// Creating context
const context = createContext(user);
// Returning context
return context;
}
export default UserContext;
Problem
When I debugg option 1, console.log(user) returns the object. Instead, option 2, console.log(user) returns undefined. What I'm missing?
import React, { useEffect, useState, useContext } from 'react';
import UserContext from './UserContext';
const ProjectSelector = (props) => {
const user = useContext(UserContext);
console.log(user);
return(...);
}
export default App;
one thing i would suggest is move this logic to a react component itself.
anhow you need to use a Provider in which you will set value to be the value consumers need to consume.useEffect is greatway to do asynchronous updates, like your requirment.
so , use a state variable as value of provider.in useEffect you fetch the data and update the state variable which in turn will update context value.
following is the code
UserContext.js
import { createContext } from "react";
const UserContext = createContext();
export default UserContext;
App.js
export default function App() {
const [user, setUser] = useState();
useEffect(() => {
console.log("here");
fetch("https://reqres.in/api/users/2")
.then(response => {
return response.json();
})
.then(data => {
setUser(data);
});
}, []);
return (
<div className="App">
<UserContext.Provider value={user}>
<DummyConsumer />
</UserContext.Provider>
</div>
);
}
DummyConsumer.js
import React, { useContext } from "react";
import UserContext from "./UserContext";
const DummyConsumer = () => {
const dataFromContext = useContext(UserContext);
return <div>{JSON.stringify(dataFromContext)}</div>;
};
export default DummyConsumer;
demo:anychronus context value providing

Why am I getting "useContext is not a function" or "context is not defined"?

I am trying to use context in my stateless component. I updated my react to v16.8.0 and added useContext, however, I keep getting these two errors and don't know what else to do. Here is my code:
import React, { useState } from "react";
import axios from "axios";
import { LanguageContext } from "./languageContext";
import { useContext } from "react";
function StripeButton() {
const context = useContext(LanguageContext);
const stripe = Stripe("pk_live_5PjwBk9dSdW7htTKHQ3HKrTd");
const [error, setError] = useState();
const handleClick = () => {
stripe
.redirectToCheckout({
...
});
};
return (
<div>
<button
id="UrgentCheckedButtonYES"
className="btn-primary"
onClick={handleClick}
>
{this.context.main.name}
<br />
</button>
<div>{error}</div>
</div>
);
}
export default StripeButton;
StripeButton.contextType = LanguageContext;
You need to import useContext like this:
import { useContext } from 'react';
const { useContext } = React
useContext is exported as method property of React
(Tested this in React 18.)
In App.js File:
import { createContext } from "react";
import ChildComponent from "./components/ChildComponent";
export const Context = createContext("Default Value");
export default function App() {
const value = "My Context Value";
return (
<Context.Provider value={value}>
<ChildComponent />
</Context.Provider>
);
}
In ChildComponent.jsx file:
import { useContext } from "react";
import { Context } from "../App";
function ChildComponent() {
const value = useContext(Context);
return <h1>{value}</h1>;
}
export default ChildComponent;
You can have as many consumers as you want for a single context. If the context value changes,then all consumers are immediately notified and re-rendered.
If the consumer isn't wrapped inside the provider, but still tries to access the context value (using useContext(Context) or <Context.Consumer>), then the value of the context would be the default value argument supplied to createContext(defaultValue) factory function that had created the context.

Resources