Not sure why react context is not using the value passed in provider?
import { createContext } from "react";
const initialState = {
isOpen: false
};
export const alertContext = createContext(initialState);
export default (props) => {
return (
<>
<alertContext.Provider value={{ isOpen: true }}>
{props.children}
</alertContext.Provider>
</>
);
};
import "./styles.css";
import { useContext } from "react";
import AlertProvider, { alertContext } from "./AlertProvider";
export default function App() {
let value = useContext(alertContext);
return (
<div className="App">
<AlertProvider>
<pre>{JSON.stringify(value)}</pre>
</AlertProvider>
</div>
);
}
Why is the value for isOpen not true?
https://codesandbox.io/s/serene-faraday-1oib3?fontsize=14&hidenavigation=1&theme=dark
You need to wrap your provider around App in index.js
as shown:
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import AlertProvider from "./AlertProvider";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<AlertProvider>
<App />
</AlertProvider>
</StrictMode>,
rootElement
);
and your app.js will look like this:
import "./styles.css";
import { useContext } from "react";
import { alertContext } from "./AlertProvider";
export default function App() {
let value = useContext(alertContext);
return (
<div className="App">
<pre>{JSON.stringify(value)}</pre>
</div>
);
}
Related
I keep getting an error when I try to use Context API for dark/light mode in App.js
Theme.js
import React, { useState } from "react";
export const ThemeContext = React.createContext();
//theme = light, dark
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("dark");
const toggleTheme = () => {
if (theme === "light") setTheme("dark");
else setTheme("light");
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
App.js
import { ThemeContext, ThemeProvider } from "./app/utility/ThemeManager";
export default function App() {
const { theme } = useContext(ThemeContext); // This is throwing the error
return (
<ThemeProvider>
...//Rest of my app
//How I'd like to use my theme
<StatusBar style={theme === "dark" ? "light" : "dark"} />
</ThemProvider>
);
};
I'd like to understand why this is throwing the error and how I could fix it?
Thanks in advance!
Import ThemeProvider in index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "./Theme.js";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
rootElement
);
and in App.js
import {ThemeContext} from "./Theme.js"
import StatusBar from './StatusBar';
import {useContext} from 'react'
export default function App() {
const { theme } = useContext(ThemeContext);
return (
<>
..... Rest Of your Code
</>
);
};
I have the following modules for my React app:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import MainApp from './MainApp';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<MainApp />
</React.StrictMode>,
document.getElementById('root')
);
MainApp.js
import React from 'react';
import App from './containers/app';
import './App.css';
import {ConnectedRouter} from 'connected-react-router'
import {Provider} from 'react-redux';
import {Route, Switch} from 'react-router-dom';
import configureStore, {history} from './store';
export const store = configureStore();
const MainApp = () =>
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route path="/" component={App}/>
</Switch>
</ConnectedRouter>
</Provider>;
export default App;
store/index.js
import {applyMiddleware, compose, createStore} from 'redux';
import reducers from '../reducers/index';
import {createBrowserHistory} from 'history'
import {routerMiddleware} from 'connected-react-router';
import createSagaMiddleware from 'redux-saga';
import rootSaga from '../sagas/index';
const history = createBrowserHistory();
const routeMiddleware = routerMiddleware(history);
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware, routeMiddleware];
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default function configureStore(initialState) {
const store = createStore(reducers(history), initialState,
composeEnhancers(applyMiddleware(...middlewares)));
sagaMiddleware.run(rootSaga);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/index', () => {
const nextRootReducer = require('../reducers/index');
store.replaceReducer(nextRootReducer);
});
}
return store;
}
export {history};
containers/dataviewer/index.js
import React from 'react';
import {connect} from 'react-redux';
import {
connectPath
} from '../../actions/Paths';
import Button from '#material-ui/core/Button';
import ButtonGroup from '#material-ui/core/ButtonGroup';
import TabularViewer from './TabularViewer';
import CollapsableViewer from './CollapsableViewer';
import ChartViewer from './ChartViewer';
class DataViewer extends React.Component {
constructor() {
super();
this.state = {
displayStyle: null
}
this.handleClick = this.handleClick.bind(this);
}
handleClick = (style) => {
this.setState({displayStyle: style})
}
DisplayControllers = () => {
return (
<ButtonGroup variant="text" color="primary" aria-label="outlined primary button group">
<Button color={this.state.displayStyle === 'tabular'? 'secondary': 'primary'} onClick={() => this.handleClick('tabular')}>Tabular</Button>
<Button color={this.state.displayStyle === 'collapsable'? 'secondary': 'primary'}onClick={() => this.handleClick('collapsable')}>Colapsable</Button>
<Button color={this.state.displayStyle === 'chart'? 'secondary': 'primary'} onClick={() => this.handleClick('chart')}>Gráfico</Button>
</ButtonGroup>
)
}
DisplayComponent = () => {
switch (this.state.displayStyle) {
case 'tabular':
return <TabularViewer />
case 'collapsable':
return <CollapsableViewer />
case 'chart':
return <ChartViewer />
default:
return <p>Seleccione un estilo de desplegado.</p>;
}
}
render() {
return (
<div>
<p>Data Viewer</p>
<this.DisplayControllers />
<this.DisplayComponent />
</div>
)
}
}
const mapStateToProps = ({paths}) => {
const {connection, path, data} = paths;
return {
connection,
path,
data
}
}
export default connect(mapStateToProps, {connectPath})(DataViewer)
Te problem is that I get the following error when the component is mounted:
Error: Could not find "store" in the context of "Connect(DataViewer)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(DataViewer) in connect options.
I can't see what I am missing.
EDIT
containers/app.js
import React from 'react';
import DataViewer from './DataViewer';
class App extends React.Component {
render() {
return (
<div className="App">
<header className="App-header">
<DataViewer
database_host="127.0.0.1'"
database_port="5432"
database_name="TCDigital"
database_user="postgres"
database_password="xxxx"
path="Ventas"
displayStyle="collapsable"
/>
</header>
</div>
);
}
}
export default App;
Why is useContext undefined?
Context
import React from 'react'
const PathContext = React.createContext()
export default PathContext
from a jsx file
import PathContext from '../../../contexts/pathContext';
.......
<PathContext.Provider
value={{
paths,
pathChecks
}}
>
<MyComponent />
</PathContext.Provider>
In MyComponent.jsx render function..
import PathContext from 'path/to/file';
import {useContext} from 'react';
const {
paths,
pathChecks
} = useContext(PathContext);
UNDEFINED!
What is my context undefined?
Use it like so:
App.js (or Main Component)
// App.js
import React from "react";
import MyContext from "./PathContext";
import MyComponent from "./MyComponent";
export default function App() {
return (
<div className="App">
<MyContext>
<MyComponent />
</MyContext>
</div>
);
}
PathContext.js
// PathContext.js
import React, { createContext } from "react";
export const PathContext = createContext(); // regular export
// A new component that will hold the context values and will wrap your <MyComponent>
const MyContext = ({ children }) => {
const paths = "define your paths";
const pathChecks = "define your pathChecks";
return (
<PathContext.Provider
value={{
paths,
pathChecks
}}
>
{children} // Pass children props
</PathContext.Provider>
);
};
export default MyContext; // default export MyContext component
MyComponent.js (context consumer)
// MyComponent.js
import React, { useContext } from "react";
import { PathContext } from "./PathContext";
const MyComponent = () => {
const { paths, pathChecks } = useContext(PathContext);
return (
<div>
<div>{paths} value</div>
<div>{pathChecks} value</div>
</div>
);
};
export default MyComponent;
Here is a sandbox example.
I think you need to use {useContext} from 'react' instead of {useContext} from React
Please check this example. It is working fine.
import React, {useContext, useEffect, useReducer, useState} from 'react';
import PathContext from "./PathContext";
function PathContextExample() {
const paths = 'this is path';
const pathChecks = 'this is path checks';
return (
<div>
<PathContext.Provider
value={{
paths,
pathChecks
}}
>
<MyComponent/>
</PathContext.Provider>
</div>
)
}
export default PathContextExample;
function MyComponent() {
const {
paths,
pathChecks
} = useContext(PathContext);
return (
<div>
{paths}
<br/>
{pathChecks}
</div>
)
}
In MyComponent.jsx file you should import PathContext
I'm trying to reach a value using React Hook useContext, but keep getting the following error:
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
CartContext.js
import React, {useState, createContext} from 'react';
export const CartContext = createContext();
export const CartProvider = (props) => {
const [cart, setCart] = useState([]);
return (
<CartContext.Provider value={[cart, setCart]}>
{props.children}
</CartContext.Provider>
)
}
And im trying to reach it from Cart.js
import React, {useContext} from 'react'
import {CartContext} from '../../pages/contact/CartContext';
import { slide as Menu } from 'react-burger-menu'
import './Cart.css'
export default function Cart() {
const [cart, setCart] = useContext(CartContext); //This line causes the error
return (
<div>
<Menu right width={350}
isOpen={false}
id={"testi"} className={ "my-menu" }
customBurgerIcon={<i className="fa fa-shopping-cart" aria-hidden="true"/>}
burgerButtonClassName={ "cartButton" }>
<h1>Hello</h1>
</Menu>
</div>
)
}
It seems alright. See this CodeSandbox:
https://codesandbox.io/s/eager-brattain-2zhxj
index.js
import React from "react";
import ReactDOM from "react-dom";
import Cart from "./Cart";
import { CartProvider } from "./CartContext";
import "./styles.css";
function App() {
return (
<CartProvider>
<Cart />
</CartProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
CartContext.js
import React, { useState, createContext } from "react";
export const CartContext = createContext();
export const CartProvider = props => {
const [cart, setCart] = useState(["a", "b"]);
return (
<CartContext.Provider value={[cart, setCart]}>
{props.children}
</CartContext.Provider>
);
};
Cart.js
import React, { useContext } from "react";
import { CartContext } from "./CartContext";
function Cart() {
const [cart, setCart] = useContext(CartContext);
function updateCart() {
setCart(prevState => {
const newState = Array.from(prevState);
newState.push("c");
return newState;
});
}
return (
<React.Fragment>
<div>I am Cart</div>
<div>Cart value: {JSON.stringify(cart)}</div>
<button onClick={updateCart}>Add 'c' to cart</button>
</React.Fragment>
);
}
export default Cart;
I am using Redux with my reactjs app. I strucking with 2 doubts here.
I would like to create multiple instace of redux based component
I like to control / show the store data to other component too..
how to achieve the both? any one help me?
I tried like this: got error:
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import reducer from "./reducer";
import App from "./App";
import Source from "./Source"; //how to get store data here too..
import "./styles.css";
var store = createStore(reducer);
const rootElement = document.getElementById("container");
ReactDOM.render(
<Provider store={store}>
<App />
<App /> //throws error
</Provider>,
rootElement
);
Live Demo
The Provider tag should contain a single React child element. You can overcome this by creating a fake Higher-Order-Component as below:
const Aux = props => props.children;
Please try the below code:
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import reducer from "./reducer";
import App from "./App";
import Source from "./Source";
import "./styles.css";
var store = createStore(reducer);
const Aux = props => props.children;
const rootElement = document.getElementById("container");
ReactDOM.render(
<Provider store={store}>
<Aux>
<App />
<App />
</Aux>
</Provider>,
rootElement
);
You must connect your component at Redux Store like this:
import React, { Component } from "react";
import { connect } from "react-redux";
class Source extends Component {
render() {
const { counter, increaseCount, decreaseCount } = this.props;
return (
<div className="container">
<h1>How to show count here?</h1>
<h2>{counter}</h2>
<button
onClick={() => {
increaseCount();
}}
>
How to increase count?
</button>
</div>
);
}
}
const mapStateToProps = state => ({
counter: state.count
});
var increaseAction = { type: "increase" };
var decreaseAction = { type: "decrease" };
const mapDispatchToProps = dispatch => {
return {
increaseCount: function() {
return dispatch(increaseAction);
},
decreaseCount: function() {
return dispatch(decreaseAction);
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Source);