I have navigation constant which is an array of objects(web-store mega-nav). I need to use context provider and when I'm trying to use my context it's telling me NavContext' is not defined no-undef.
NavContext.js
import { createContext } from 'react'
const navigation = [...] // array of objects
const NavContext = createContext(navigation)
export default NavContext
Nav.js
import {createContext} from 'react'
import NavContext from './context/NavContext' //added
function Nav() {
return (
<NavContext.Provider> //deleted value
// childrens
</NavContext.Provider>
)
}
Sidebar.js
//then in one of the child I'm trying to call it:
import { useContext } from 'react'
import NavContext from '../context/NavContext' //added
function Sidebar(){
const nav = useContext(NavContext)
return (
{nav.map(...)} // nav is undefined
)
}
Now nav constant is undefined when I'm using useContext
You need to export the create context like this
export const NavContext = createContext(navigation)
Then import it into your child component like this
import { NavContext} from "../Nav";
//Create a new NavContext.js File.
import React, { createContext, useReducer } from "react";
export const NavContext = createContext();
const initialState = {
}
function reducer(state, action) {
return { ...state, ...action };
}
export const NavProvider = (props) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<NavContext.Provider value={{ state, dispatch }}>
{props.children}
</NavContext.Provider>
);
};
Then in your index.js file.
import { NavProvider} from "./NavContext";
ReactDOM.render(
<NavProvider>
<App />
</NavProvider>,
document.getElementById("root")
);
If that doesnt work idk what will.
Try not to pass any arguments into createContext, then pass navigation into Context provider as prop
<Context.Provider value={navigation} />
And then get the value using useContext Hook in your consumer component
For my knowledge, you have to import useContext like this.
import React, { useContext } from 'react'
Related
i have been trying to implement a context api solution since i want to use children states(data) in my app.js without lifting up the states. anyways i have tried to implement it a context api soloution to by doing the following :
i created a folder names context and then created Context.js
the code is as follows:
mport { createContext,useState } from "react";
export const Mycontext = createContext()
const Context = ({children}) =>{
const [post, setPost] = useState([])
return(
<Mycontext.Provider value={[post,setPost]}>
{children}
</Mycontext.Provider>
)
}
export default Context
i wrapped the index.js file with the Provider wrapper as follows:
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import Context from './context/Context';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Context>
<App />
</Context>
);
my main goal for now is to use useState hook data or states so i can use them in higher up comonents , in this case i want my post.js file to change usestate data in context so i can then use that data to post something in App.js using a container component that takes value as a props
i will post the both post.js and container.js and app.js below
import React,{useContext,useState,useEffect,useRef} from 'react'
import '../HomeMainStyling/HomeStyling.css'
import Tweets from './Tweets'
import Context from '../../context/Context'
function Tweet() {
const tw = useRef('')
const {post,setPost} = useContext(Context);
useEffect(() => {
if (post.length) console.log(post);
}, [post]);
function PostNow(event){
event.preventDefault();
setPost((oldpost) => [tw.current.value,...oldpost]);
}
return (
<div className="tweetcontainer">
<textarea ref={tw} className="tweetinfo"></textarea>
<button className="postIt" onClick={PostNow}>tweet</button>
</div>
)
}
export default Tweet
//
the container is the following:
import React from 'react'
import '../HomeMainStyling/HomeStyling.css'
function Tweets({value}) {
return (
<h2>{value}</h2>
)
}
export default Tweets
App.js:
import Tweet from './Center/HomeMain/Tweet';
import Tweets from './Center/HomeMain/Tweets';
import { useContext,useState } from 'react';
import Context from './context/Context';
function App() {
const {post,setPost} = useContext(Context);
return (
<div className="App">
<Tweet/>
<Tweets value={post}/>
</div>
);
}
export default App;
the app should in principle post 1 h1 element for every click in Tweet components
The useContext hook takes the context you created using createContext() as a parameter, but you are passing a custom component to it, so try:
import { Mycontext } from './context/Context';
const [post, setPost] = useContext(Mycontext)
<Mycontext.Provider value={[post,setPost]}>
this is wrong you ahve to write
<Mycontext.Provider value={{post,setPost}}>
In my react application I am trying to use context api. In my component I am importing the context but it is giving error that object can not destructure the property. I am trying to implement cart functionality in my app. I am using hooks.
ImgContext.js
import React, { createContext, useState } from 'react';
const ImgContext = createContext();
const ImgConProvider = ({children}) => {
const [myCart, setMyCart] = useState([]);
return(
<ImgContext.Provider value={{myCart, setMyCart}}>
{children}
</ImgContext.Provider>
)
}
export {ImgContext, ImgConProvider}
ImageGrid.js
import React, { useContext, useState } from 'react';
import ImageGrid from './ImageGrid';
import { ImgContext } from './Context/ImageContext';
const Home = () => {
const { myCart } = useContext(ImgContext);
return (
<div className="App">
{myCart}
</div>
)
}
export default Home;
You are not providing a a default value when creating the context. If there is a scenario where the component doenst have access to a provider the value from context would be undefined which maybe causing the issue.
Better provide a default value.
const ImgContext = createContext({});
I've made two different windows with react and provide same store. But if i change store data in one window, second window doesn't changed. And idk know how to synchronize.(All Reducers and Actions made as on default React project)
First provide(index.js):
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {Provider} from 'react-redux';
import store from "../redux/store";
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById("root"))
First App.js:
import React, {useEffect, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";
import {addNumberAction} from "../redux/addNumber";
export default function App() {
const {number} = useSelector(state=>state.testPage)
const dispatch = useDispatch();
let changeNumber = number
return (
<>
<h1>First</h1>
<button onClick={()=>dispatch(addNumberAction(++changeNumber))}>{number}</button>
</>
)
}
Second provide(index.js):
import React from 'react';
import ReactDOM from 'react-dom'
import App from "./App";
import {Provider} from "react-redux";
import store from "../redux/store";
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById("root2")
)
Second App.js:
import React, {useEffect} from 'react';
import {useDispatch, useSelector} from "react-redux";
import {addNumber, addNumberAction} from "../redux/addNumber";
export default function App() {
const {number} = useSelector(state=>state.testPage)
const dispatch = useDispatch();
let changeNumber = number
return (
<>
<h1>Second</h1>
<button onClick={()=>dispatch(addNumberAction(++changeNumber))}>{number}</button>
</>
)
}
They are not the same store. Each time you use <Provider store={store}> it basically create a store for any components inside it. Calling two <Provider store={store}> will create 2 independent store.
I tried to configure redux state to share state between browser’s windows. At the end, I found info, how it can be with hook.
For example,
import React, { useState, useEffect } from "react";
function HelloStorage() {
const [name, setName] = useState("");
useEffect(() => {
localStorage.setItem("name", name);
}, [name]);
useEffect(() => {
const onReceiveMessage = (e) => {
const { key, newValue } = e;
if (key === "name") {
setName(newValue);
}
};
window.addEventListener("storage", onReceiveMessage);
return () => {
window.removeEventListener("storage", onReceiveMessage);
};
}, []);
const handleChange = (e) => {
setName(e.target.value);
};
return <input value={name} onChange={handleChange} />;
}
For this link you can find information, how create a custom React Hook to share state between browser tabs without Redux state.
You can use redux-state-sync for that (https://www.npmjs.com/package/redux-state-sync).
Lets say you create the store currently like this:
import { configureStore } from '#reduxjs/toolkit';
export const store = configureStore({
reducer
});
All you need is adding the middleware to the store:
import { configureStore } from '#reduxjs/toolkit';
import { createStateSyncMiddleware, initMessageListener } from 'redux-state-sync'
export const store = configureStore({
reducer,
middleware: [createStateSyncMiddleware()],
});
initMessageListener(store);
I need to use dispatch Context API methods in _app.js.
The main limitation is that I use React hooks along with Context API, since _app.js is a Class, I can't use hooks within it.
My code:
// store.js
import React, { createContext, useContext, useReducer } from "react";
import mainReducer from "../store/reducers";
const AppStateContext = createContext();
const AppDispatchContext = createContext();
const initialState = {
filters: {
diet: {
selected: []
}
}
};
const useAppState = () => useContext(AppStateContext);
const useAppDispatch = () => useContext(AppDispatchContext);
const useApp = () => [useAppState(), useAppDispatch()];
const AppProvider = ({ children }) => {
const [state, dispatch] = useReducer(mainReducer, initialState);
return (
<AppStateContext.Provider value={state}>
<AppDispatchContext.Provider value={dispatch}>
{children}
</AppDispatchContext.Provider>
</AppStateContext.Provider>
);
};
export { AppProvider, useAppState, useAppDispatch, useApp };
// _app.js
import App from "next/app";
import React from "react";
import { AppProvider } from "../store";
class MyApp extends App {
componentDidMount() {
/***********************************/
// HERE I WOULD LIKE TO USE DISPATCH
/***********************************/
}
render() {
const { Component, router, pageProps } = this.props;
return (
<AppProvider>
<Component {...pageProps} />
</AppProvider>
);
}
}
export default MyApp;
If you really want to use hooks, then just put a wrapper around _app.js like this:
import React from 'react'
import App from 'next/app'
function MyComponent({ children }) {
// You can use hooks here
return <>{children}</>
}
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return (
<MyComponent>
<Component {...pageProps} />
</MyComponent>
)
}
}
export default MyApp
i am trying to include my common component in my main.js
this one I did it it successfully.
but in my common component, I am trying to print my redux data values.
so I created a method called handleClickForRedux to print the values.
I have included mapStateToProps and mapDispatchToProps
but still value is not printing at this line. console.log("event reddux props--->", props);
can you tell me how to fix it.
providing my code snippet and sandbox below.
https://codesandbox.io/s/react-redux-example-265sd
scroll.js
import React, { useEffect, useState, Fragment } from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
//import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import Typography from "#material-ui/core/Typography";
import Drawer from "#material-ui/core/Drawer";
import { bindActionCreators } from "redux";
import * as actionCreators from "../actions/actionCreators";
import { connect } from "react-redux";
import { compose } from "redux";
function SportsMouse(classes, props) {
// const [canEdit, setCanEdit] = useState(false);
function handleClickForRedux(event) {
console.log("event--->", event);
console.log("event reddux props--->", props);
}
return (
<Card>
<div onClick={handleClickForRedux}>I am here </div>
</Card>
);
}
SportsMouse.propTypes = {
classes: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
posts: state.posts,
comments: state.comments
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch);
}
export default compose(
connect(
mapStateToProps,
mapDispatchToProps
)
)(SportsMouse);
main.js
import React from "react";
import { Link } from "react-router-dom";
import Scroll from "../commonComponents/scroll";
const Main = props => {
const { children, match, ...rest } = props;
return (
<div>
<h1>
<Scroll />
<Link to="/">Reduxstagram</Link>
</h1>
{React.Children.map(children, child => React.cloneElement(child, rest))}
</div>
);
};
export default Main;
Even when using material-ui, components only accept one argument. classes exists inside props. If you console.log(classes) you'll see that it contains all of your props, including material-ui's styles. It should be this:
function SportsMouse(props) {