React Context code not working despite passing proper context - reactjs

As per the first example at [https://reactjs.org/docs/context.html] the following code should work, but it is not working. Any help? Am I misunderstanding something?
App.js:
import "./App.css";
import React from "react";
import Level1_Child1 from "./Level1_Child1";
import Level1_Child2 from "./Level1_Child2";
export default function App() {
return (
<React.Fragment>
<AppContext.Provider
value={{
String1: "AppContext Passed String1",
String2: "AppContext Passed String2",
}}>
<Level1_Child1 />
<Level1_Child2 />
</AppContext.Provider>
</React.Fragment>
);
}
export const AppContext = React.createContext({
String1: "AppContext Default String1",
String2: "AppContext Default String2",
});
Level1_Child2.js:
import React from "react";
import Level2_Child1 from "./Level2_Child1";
export default function Level1_Child2(Props) {
return (
<React.Fragment>
<h4>H4 element - Level1_Child2 - React.Fragment</h4>
<Level2_Child1 />
</React.Fragment>
);
}
Level2_Child1.js:
import React from "react";
import AppContext from "./App";
export default class Level2_Child1 extends React.Component {
render() {
let aquiredContext = this.context;
return (
<React.Fragment>
<p>
Props passed using context : {aquiredContext.String1}
{aquiredContext.String2}
</p>
</React.Fragment>
);
}
}
Level2_Child1.contextType = AppContext;
The output is as follows :
Level1_Child1 not pasted here as it does not concern us here.

After trying for almost 2 days, I tried the following which successfully resolved my above mentioned issue. Created a seperate .js file for the context object and imported it in the necessary files, which automatically resolved the issue without doing ANY further changes to the code.
AppContext.js:
import React from "react";
let AppContext = React.createContext({
String1: "AppContext Default String1",
String2: "AppContext Default String2",
});
export default AppContext;
Before this, it was showing the following error in the Firefox console:
Redefining it in the AppContext.js separately, resolved the issue. Don't know why, the same code was giving above error when defined in App.js.

Related

UseContext can't find variable?

I'm trying to understand useContext but I don't see what I'm doing wrong here, I get the error message "Can't find variable: Test" but in the tutorial I'm reading from it never says anything about needing to import/export other than what is in the code?
Thank you!
App.js
import React, { createContext } from 'react';
const Test = createContext()
export default function App() {
return (
<Test.Provider value="hello">
<Home/>
</Test.Provider> );
}
Home.js
const Home = () => {
return(
<Test.Consumer>
<View style={styles.homeContainer}>
{value}
</View>
</Test.Consumer>
)
}
You aren't exporting Test from App.js, so you can't just implicitly use it in Home.js.
I'd recommend moving it to another file, say, contexts.js:
import React from 'react';
const Test = React.createContext();
export {Test};
You can then do
import {Test} from './contexts';
in both (or all, in the future) of your other source files to refer to the same context type.
I suggest you to create the context in a separate file :
test-context.js
import { createContext } from 'react';
export const TestContext = createContext();
App.js
import React from 'react';
import { TestContext } from './test-context';
export default function App() {
return (
<TestContext.Provider value="hello">
<Home/>
</TestContext.Provider>
);
}
In TestContext.Consumer, you must provide a function to consume the context value.
Home.js
import React from 'react';
import { TestContext } from './test-context';
export default const Home = () => {
return (
<TestContext.Consumer>
value => (
<View style={styles.homeContainer}>
{value}
</View>
)
</TestContext.Consumer>
)
}
We often forget about old school rules, when reading docs about fancy libraries these days.
In your example, Context is just a JS object, in order to access Test.Consumer, Test must be in scope of the file.
So, you have to import Test object (context) on order to access the Consumer property.

ReactJS: Problem accessing this.context in a class based consumer component

I have a problem to access this.context in a class based consumer component. I have the following situation:
AppContext.js:
import React from "react";
const ContactContext = React.createContext(); // Create our context
export default ContactContext;
DataProvider.js:
import React, { Fragment } from "react";
import AppContext from "./AppContext";
export default class DataProvider extends React.Component {
state = {
contacts: {
contact1: {
id: 1,
firstName: 'Test User FN',
lastName: 'Test User LN'
}
}
};
render() {
return (
<>
<AppContext.Provider value={{contacts: this.state.contacts}}>
{this.props.children}
</AppContext.Provider>
</>
);
}
}
App.js:
import React from 'react';
import DataProvider from "./DataProvider";
import Contact from './components/contact/contact.component';
export default class App extends React.Component {
render() {
return (
<div>
<div className="container">
<DataProvider>
<Contact contactIndex={0}/>
</DataProvider>
</div>
</div>
);
}
}
The consumer Contact.js:
import React, { Component } from "react";
import AppContext from '../context/AppContext'
export default class Contact extends Component {
static contextType = AppContext;
componentDidMount () {
console.log('My context is: ' + this.context);
}
render() {
return (
<div className="card"></div>
);
}
}
The console output is:
My context is: undefined
Thanks for any help
Regards
Dakir
Only difference I see in the other answer's CodeSandbox is the import path is different.
import AppContext from "./AppContext";
vs:
import AppContext from '../context/AppContext'
Maybe OP has a filepath/import error?
p.s. If this is the error, TypeScript is a lifesaver for avoiding these kind of things in JS.
Your code seems right to me, I tried to replicate it in a Sandbox to find out the error and somehow works like a charm.
https://codesandbox.io/s/interesting-https-emgoz?file=/src/App.js
Tried to spot the difference but I couldn't honestly.

React context provider does not show defaults

I am trying to keep things organized with my project. So I created a config folder in which I placed a context folder. Inside the context folder I want to handle all things context.
So I have index.ts which is as follows:
import { ThemeContextProvider } from './context';
export default ThemeContextProvider;
And a context.tsx file with the following:
import { createContext } from 'react';
export const ThemeContext = createContext({});
export const ThemeContextProvider = ThemeContext.Provider;
In my app.tsx I have
import React from 'react';
import ThemeContextProvider from './config/context';
import theme from './theme';
export default function App() {
return (
<ThemeContextProvider value={theme}>
...
</ThemeContextProvider>
);
}
The above works. But I want to move the theme into context.tsx and load it there as default so I keep my App.tsx as clean as possible
So in context.tsx I change to:
import { createContext } from 'react';
import theme from '../../theme';
export const ThemeContext = createContext(theme);
export const ThemeContextProvider = ThemeContext.Provider;
And in App.tsx I change <ThemeContextProvider value={theme}> to <ThemeContextProvider>
React immediately complains about <ThemeContextProvider> and wants the value prop. When I pass value={} and try to get default values from the context, they are no longer there.
Any ideas what's going on and advise about how to handle it, and also advise about best practices? Perhaps I'm going at it incorrectly?
You can create another component that wraps the content and passes the theme to the context provider
import { createContext } from 'react';
import theme from '../../theme';
export const ThemeContext = createContext({});
export const ThemeContextProvider = ThemeContext.Provider;
export const YourContextProvider = ({ children }) => (
<ThemeContextProvider value={theme}>
{children}
</ThemeContextProvider>;
);
and then use it in the app component
import React from 'react';
import YourContextProvider from './config/context';
export default function App() {
return (
<YourContextProvider>
...
</YourContextProvider>
);
}
You can still name the YourContextProvider as ThemeContextProvider if you want but I'd recommend not. It may be hard to follow for the future maintenance.

warning : is defined but never used

I created a jsxUses.js file in the components folder, but when I import it in App.js its shows warning: 'jsxUses' is defined but never used
//This is App.js file
import React, { Component } from 'react';
import './App.css';
import jsxuses from './components/jsxUses';
class App extends Component{
render() {
return (
<div className="App">
<jsxuses/>
</div>
);
}
}
export default App;
and this is jsxUses.js file
import React from 'react'
const jsxuses = () => {
return (
<div>
<h1> Hey there!</h1>
</div>
);
}
export default jsxuses;
React Element should be PascalCased. So it should be
import JsxUses from './components/jsxUses';
...
<JsxUses />
Change your jsxUses.js as:
...
const JsxUses = () => {
...
export default JsxUses;
And your App.js as:
import JsxUses from './components/jsxUses';
...
<JsxUses />
React file structure naming is unopinionated but React elements should be PascalCase for React to know whether or not you're using a function, class or an HTMLelementPascalCased.
Look for more here: Is there an official style guide or naming convention for React based projects?
Hope this helps!
Actually you should avoid using small latter for custom tags.
so you should do
const JsxUses = () => {
...
}
export default JsxUses
and
import JsxUses from './components/jsxUses';
or if you want to write like -
const jsxuses = () => {
...
}
export default jsxuses
then you should import it like
import { default as JsxUses } from './components/jsxUses'
Well, Use import JsxUses from './components/JsxUses'; React component name should be PascalCase.

useContext(Context) show warning on console in React Native

I have use React Context API hook in react native. I created Consumer and Provider both to pass props and state from parent to child. Code is working perfectly fine, I have received props from parent to child.
I have received following warning on my console:-
Warning: Calling useContext(Context.Consumer) is not supported, may
cause bugs, and will be removed in a future major release. Did you
mean to call useContext(Context) instead?
Please check below added code:-
I have create common context file CommonContext.js.
import React, {createContext} from 'react';
const MyContext = createContext();
export const LoginProvider = MyContext.Provider;
export const LoginConsumer = MyContext.Consumer;
This is my provider code
import React, {PureComponent} from 'react';
import {View, Text} from 'react-native';
import {LoginProvider} from './CommonContext';
export default class Login extends PureComponent {
constructor(props) {
super(props);
}
render() {
return (
<View style={Styles.mainContainer}>
<LoginProvider value={this.props}>
<LoginScreenView />
</LoginProvider>
</View>
);
}
}
From this way i am access parent component data into child hook
import {LoginConsumer} from './CommonContext';
export default function LoginScreenView(props) {
let loginConsumer = useContext(LoginConsumer);
return (
<View style={Styles.mainContainer}>
<Text>{loginConsumer}</Text>
</View>
);
}
You are receiving this error because you are calling useContext on a Context.Consumer instance, instead of a Context.
You do like this:
export const LoginConsumer = MyContext.Consumer;
and then you call useContext on LoginConsumer:
let loginConsumer = useContext(LoginConsumer);
Instead, you should call useContext on MyContext, like this:
Export the context from CommonContext.js:
export const MyContext = createContext();
Import the context instead of the context consumer in the file where you're using it:
import { MyContext } from './CommonContext';
and then using it with useContext:
let login = useContext(MyContext);
So your second component that you posted would look like this:
import { MyContext } from './CommonContext';
export default function LoginScreenView(props) {
let login = useContext(MyContext);
return (
<View style={Styles.mainContainer}>
<Text>{login}</Text>
</View>
);
}

Resources