Reputation: 2091
I am using the new React Context API and I need to get the Consumer data from the Context.Consumer variable and not using it inside the render method. Is there anyway that I can achieve this?
For examplify what I want:
console.log(Context.Consumer.value);
What I tested so far: the above example, tested Context.Consumer currentValue and other variables that Context Consumer has, tried to execute Context.Consumer() as a function and none worked.
Any ideas?
Upvotes: 33
Views: 54913
Reputation: 2339
Here is a sample code from what I was trying for myself. Hope it helps.
import React from 'react';
const ThemeContext = React.createContext('light');
class ThemeContextComponent extends React.Component {
static contextType = ThemeContext;
render() {
return <div>Testing the {this.context} </div>;
}
}
function useTask(context) {
return React.useContext(context);
}
function ThemeFunctionUseContextComponent(props) {
return (
<div>
ThemeFunctionUseContextComponent: Testing the {useTask(ThemeContext)}{' '}
</div>
);
}
function ThemeFunctionContextComponent(props) {
var contextType = ThemeContext;
return (
<div>
ThemeFunctionContextComponent: Testing the context <br /> current Value: {contextType._currentValue}, <br />{' '}
current value 2: {contextType._currentValue2}, <br /> default value:{' '}
{contextType._defaultValue} <br /> Global Name: {contextType._globalName}{' '}
<br /> ThreadCount: {contextType._threadCount}{' '}
</div>
);
}
function ThemeFunctionUseContextComponent(props) {
var contextType = React.useContext(ThemeContext);
return (
<div>ThemeFunctionUseContextComponent: Testing the context {contextType} </div>
);
}
function WithContext(Component) {
return (props) => (
<ThemeContext.Consumer>
{(value) => <Component {...props} context={value} />}
</ThemeContext.Consumer>
)
}
function ThemeFunctionUseContextTwoComponent(props) {
return <div>ThemeFunctionUseContextTwoComponent: Testing the context={props.context} </div>;
}
var ThemeFunctionUseContextThreeComponent = WithContext(
ThemeFunctionUseContextTwoComponent
);
function ThemeComponent(props) {
return <div>ThemeComponent: Testing the {props.theme} </div>;
}
class RectorComponent extends React.Component {
render() {
return <div>RectorComponent: Testing this {this.props.theme} </div>;
}
}
export default function App() {
return (
<div>
<h1>Hello Starter!</h1>
<ThemeComponent theme="dark" />
<br />
<RectorComponent theme="dark" />
<br />
<ThemeContext.Provider value="dark">
<ThemeContextComponent />
</ThemeContext.Provider>
<br />
<ThemeContext.Provider value="dark">
<ThemeFunctionContextComponent />
</ThemeContext.Provider>
<br />
<ThemeContext.Provider value="dark">
<ThemeFunctionUseContextThreeComponent />
</ThemeContext.Provider>
<br/>
<ThemeContext.Provider value="dark">
<ThemeFunctionUseContextComponent />
</ThemeContext.Provider>
<br />
</div>
);
}
I am not sure of side effects of following code usage:
function ElementWithContextFunctionPattern(Component) {
return ((props) => (
<ThemeContext.Consumer>
{(context) => (
<ThemeFunctionUseContextTwoComponent {...props} context={context} />
)}
</ThemeContext.Consumer>
))();
}
It can be used as :
export default function App() {
return (
<ThemeContext.Provider value="dark">
<ElementWithContextFunctionPattern />
</ThemeContext.Provider>
)
}
Also have a look at this: Unable to run the function from the context
Upvotes: 0
Reputation: 11067
For the @wertzguy solution to work, you need to be sure that your store is defined like this:
// store.js
import React from 'react';
let user = {};
const UserContext = React.createContext({
user,
setUser: () => null
});
export { UserContext };
Then you can do
import { UserContext } from 'store';
console.log(UserContext._currentValue.user);
Upvotes: 2
Reputation: 3853
You can achieve this in functional components by with useContext
Hook.
You just need to import the Context from the file you initialised it in. In this case, DBContext
.
const contextValue = useContext(DBContext);
Upvotes: 11
Reputation: 17687
You can via an unsupported getter:
YourContext._currentValue
Note that it only works during render, not in an async function or other lifecycle events.
Upvotes: 2
Reputation: 99
This is how it can be achieved.
class BasElement extends React.Component {
componentDidMount() {
console.log(this.props.context);
}
render() {
return null;
}
}
const Element = () => (
<Context.Consumer>
{context =>
<BaseMapElement context={context} />
}
</Context.Consumer>
)
Upvotes: 1
Reputation: 281626
As of React v16.6.0, you can use the context API like:
class App extends React.Component {
componentDidMount() {
console.log(this.context);
}
render() {
// render part here
// use context with this.context
}
}
App.contextType = CustomContext
However, the component can only access a single context. In order to use multiple context values, use the render prop pattern. More about Class.contextType.
If you are using the experimental public class fields syntax, you can use a static class field to initialize your contextType
:
class MyClass extends React.Component {
static contextType = MyContext;
render() {
let value = this.context;
/* render something based on the value */
}
}
When what I understand from the question, to use context inside your component but outside of the render, create a HOC to wrap the component:
const WithContext = (Component) => {
return (props) => (
<CustomContext.Consumer>
{value => <Component {...props} value={value} />}
</CustomContext.Consumer>
)
}
and then use it:
class App extends React.Component {
componentDidMount() {
console.log(this.props.value);
}
render() {
// render part here
}
}
export default WithContext(App);
Upvotes: 33