I have a simple react app in which i have to use useContext.
(btw im using vite + react)
here is my code for Context.jsx
import React, {useContext} from 'react';
const emailContext = React.createContext();
export const useEmail = () => useContext(emailContext);
export const emailProvider = ({children}) => {
const currentUser = "None";
const value = {
currentUser
}
return(
<emailContext.Provider value={value}>
{children}
</emailContext.Provider>
)
}
and heres how i am using the context
import "./styles.css";
import { useEmail } from "./Context/Context"
export default function App() {
const {currentUser} = useEmail();
return (
<div className="App">
<h1>Hello CodeSandbox {currentUser}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
I am sure why I am getting error in this code.
some of the errors that I am getting
_useEmail is undefined (latest)
currentUser user is undefined
thing i have tried
Initialized createContext with some initial value (only intial value is visible).
using useContext() directy in the App.js (useContext(emailContext) return undefined)
instead of {children} used <children/>.
used useState instead of const currentUser in emailProvider
I am getting same problem even when I use typescript.
but none of the above helped.
You should wrapping app with <emailProvider></emailProvider> to using data in value={value}. Now it gets undefined from const emailContext = React.createContext();
Below code may help you analyse the flow , also check link for more details https://medium.com/technofunnel/usecontext-in-react-hooks-aa9a60b8a461
use useContext in receiving end
import React, { useState } from "react";
var userDetailContext = React.createContext(null);
export default function UserDetailsComponent() {
var [userDetails] = useState({
name: "Mayank",
age: 30
});
return (
<userDetailContext.Provider value={userDetails}>
<h1>This is the Parent Component</h1>
<hr />
<ChildComponent userDetails={userDetails} />
</userDetailContext.Provider>
);
}
function ChildComponent(props) {
return (
<div>
<h2>This is Child Component</h2>
<hr />
<SubChildComponent />
</div>
);
}
function SubChildComponent(props) {
var contextData = React.useContext(userDetailContext);
return (
<div>
<h3>This is Sub Child Component</h3>
<h4>User Name: {contextData.name}</h4>
<h4>User Age: {contextData.age}</h4>
</div>
);
}
Related
I'm passing the value of my state using useContext. However it keeps on saying that "toggle" is undefined how do i solved this part that the value of toggle can be passed to mainSection?
Here's my code
import React, { useState, createContext } from 'react';
import ReactDOM from 'react-dom';
const languages = ['JavaScript', 'Python'];
export const reactContext = React.createContext()
function App() {
const [toggle,setToggle] = useState(false)
// implement Context here so can be used in child components
return (
<reactContext.Provider value={{toggle,setToggle}}>
<MainSection />
</reactContext.Provider >
);
}
function MainSection() {
console.log(toggle)
return (
<div>
<p id="favoriteLanguage">Favorite programing language: {languages[0]}</p>
<button id="changeFavorite" onClick={() => console.log(toggle)}>Toggle language</button>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
you are missing useContext. At the same time you should likely use ReactContext instead of reactContext.
function MainSection() {
const { toggle, setToggle } = useContext(reactContext) // <-- you are missing this line
console.log(toggle)
return (
<div>
<p id="favoriteLanguage">Favorite programing language: {languages[0]}</p>
<button id="changeFavorite" onClick={() => console.log(toggle)}>Toggle language</button>
</div>
)
}
Docs - https://reactjs.org/docs/hooks-reference.html#usecontext
I'm trying to give one component the array value at a certain index and assign a value that i want from the child component.
I want it like this because I'm trying to do a survey app and the number of question can be different. this is just a little test that concludes what I want.
the base Component
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState([]);
results.length = 20;
results[3] = 'kiss';
results[2] = [12, 454, 45];
console.log(results);
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results[5]}/>
<button onClick={() => console.log(results)}> SHOW </button>
</div>
);
}
the component
import React, { useState } from 'react';
const Comp = ({result}) => {
result = 1
console.log(result)
return (
<div>
hhhhh
</div>
);
}
export default Comp
here is a place I set it up => https://stackblitz.com/edit/react-mfpk5f?file=src%2FApp.js,src%2FComponent.js
every suggestion is highly appreciated!
parent componentHere i have tried a way to find solution ,
just keep a callback function in child component and call a function of parent component inside child so that u can pass data to it .
child component
If you want to add more, you use the setResults() e.g. setResults(['kiss']); so now your results='kiss', if you want more is setResults(...results,[12, 454, 45]); and now your results= kiss,12,454,45 . But:
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState(['hiii']);
function handleClick() {
const array1 = 'kiss';
const array2 = [12, 454, 45];
setResults([...results, array1, array2]);
console.log(results);
}
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results[5]} />
<button onClick={() => handleClick()}> SHOW </button>
</div>
);
}
First you need to add the values when something happened, e.g. onClick={...}.
<Comp result={results[5]}/> this is correct, but you call when the result=[] show you need to call after updating, e.g.
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState(['Hi']);
function handleClick() {
const array1 = 'kiss';
const array2 = [12, 454, 45];
setResults([...results, array1]);
console.log(results);
}
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results} />
<button onClick={() => handleClick()}> {results} </button>
<div>
{results.map(() => {
return <Comp result={results[5]} />;
})}
</div>
</div>
);
}
Of course this is NOT the best solution, but I hope you understand what happened, and like you will see you need to press the button 5 times to get something for the results[5] <Comp result={results[5]} />
and for the last you need to change the Comp:
import React, { useState } from 'react';
const Comp = ({result}) => {
const [compResults, setcompResults] = useState(result);
console.log(compResults)
return (
<div>
{compResults}
</div>
);
}
export default Comp
Can you use useState (and other react hooks?) with Server Side Rendering? Everytime I am trying to run the code below I get the error TypeError: Cannot read property 'useState' of null. However, when I comment out the getServerSideProps function at the very bottom I have no problem running the code as intended. So my questions is can useState be used with Server Side Rendering in nextjs? If the answer is yes, then where am I going wrong in the code below?
import React from "react";
import { useRouter } from "next/router";
import useSelectedGenreInfoExtractor from "../../hooks/useSelectedGenreInfoExtractor";
import { useState } from "react";
import { useEffect } from "react";
import Navbar from "../../components/Navbar";
import useFetchTrendingCatagory from "../../hooks/useFetchTrendingCatagory";
import useFetchTopRatedCatagory from "../../hooks/useFetchTopRatedCatagory";
import useFetchMovieGenreResults from "../../hooks/useFetchMovieGenreResults";
import Moviegenreresults from "../../components/Moviegenreresults";
export default function genre(props) {
const [myresultsfromhook, setMyresultsfromhook] = useState();
const [myreturnedmovies, setMyreturnedmovies] = useState();
const router = useRouter();
const { genre } = router.query;
if (genre == "Trending") {
let mymovies = useFetchTrendingCatagory();
console.log("This is a log of my props", props);
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
} else if (genre == "Top Rated") {
let mymovies = useFetchTopRatedCatagory();
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
} else {
let mymovies = useFetchMovieGenreResults(genre);
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
}
}
export async function getServerSideProps(context) {
if (context.params.genre == "Trending") {
let mymovies = useFetchTrendingCatagory();
return {
props: {
results: mymovies.results,
},
};
} else if (context.params.genr == "Top Rated") {
let mymovies = useFetchTopRatedCatagory();
return {
props: {
results: mymovies.results,
},
};
} else {
let mymovies = useFetchMovieGenreResults(genre);
return {
props: {
results: mymovies.results,
},
};
}
}
I think fundamentally the problem is the way you are using getServerSideProps.
Even thought the answer is you can not use useState inside getServerSideProps because this function run in the server, it is important to understand what getServerSideProps does and when, I think you can find very clear explanation about that in next docs.
https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props
Inside getServerSideProps use axios or the fetch api to get your data and pass it to the props.
I am not 100% sure but I thinnk inn your case you can also use Promise.all() to get the data from those three api calls.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
useState should be inside the component, it is a React hook. serverside functions are independent of React components.
I think the issue is the name of the component should be with capital letter:
// not genre
export default function Genre(props)
I am trying to understand how Props work in React. The following code is giving an error - Error: Objects are not valid as a React child (found: object with keys {args})
const App = () => {
const course = 'Half Stack application development'
return (
<div>
<Header args={course}/> // Will an object be passed or just the string?
</div>
)
}
const Header = (agrs)=>{
console.log(agrs)
return (
<div>
<h1>{agrs}</h1>
</div>
)
}
When props are being passed, is an Object is passed encapsulating the fields or just the field values are passed?
why does the above code doesn't work?
Thanks
First off, you have a spelling mistake. Replace agrs with args. Secondly, props are passed as an object (dictionary), so you have one of two options:
const Header = (props) =>{
console.log(props.args)
return (
<div>
<h1>{props.args}</h1>
</div>
)
}
or object destructuring:
const Header = ({args}) =>{
console.log(args)
return (
<div>
<h1>{args}</h1>
</div>
)
}
Also, make sure to add props validation (your linter should warn you about this):
import PropTypes from "prop-types";
Header.propTypes = {
args: PropTypes.string.isRequired
};
Answer 1: Value is passed as a key with the same name as field you assigned it to in props object.
Answer 2:
const Header = (props)=>{
console.log(props.agrs)
return (
<div>
<h1>{props.agrs}</h1>
</div>
)
}
The code above will run fine.
Alternative to answer 2:
const Header = ({agrs})=>{
console.log(agrs)
return (
<div>
<h1>{agrs}</h1>
</div>
)
}
This will also run fine.
It uses object destructuring so you don't have to use props.agrs but just args works fine.
const App = () => {
const course = 'Half Stack application development'
return (
<div>
<Header args={course}/> // Will an object be passed or just the string?
</div>
)
}
const Header = ({agrs})=>{
console.log(agrs)
return (
<div>
<h1>{agrs}</h1>
</div>
)
}
Use object Destructuring like above or
const Header = (props)=>{
console.log(props.agrs)
return (
<div>
<h1>{props.agrs}</h1>
</div>
)
}
Find more here Components and Props.
Find more about Destructuring
import React from 'react';
class App extends React.Component {
render() {
return (
<div>
<h1>{this.props.headerProp}</h1>
<h2>{this.props.contentProp}</h2>
</div>
);
}
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App headerProp = "Header from props..." contentProp = "Content
from props..."/>, document.getElementById('app'));
export default App;
enter image description here
New to React - I am trying to use multiple contexts within my App component, I tried following the official guide on multiple contexts.
Here is my current code:
App.js
import React from "react";
import { render } from "react-dom";
import Login from "./Login";
import AuthContext from "./AuthContext";
import LayoutContext from "./LayoutContext";
import LoadingScreen from "./LoadingScreen";
class App extends React.Component {
render() {
const { auth, layout } = this.props;
return (
<LayoutContext.Provider value={layout}>
<LoadingScreen />
<AuthContext.Provider value={auth}>
<AuthContext.Consumer>
{auth => (auth.logged_in ? console.log("logged in") : <Login />)}
</AuthContext.Consumer>
</AuthContext.Provider>
</LayoutContext.Provider>
);
}
}
render(<App />, document.getElementById("root"));
Login.js
import React from "react";
class Login extends React.Component {
render() {
return (
<div></div>
);
}
}
export default Login;
AuthContext.js
import React from "react";
const AuthContext = React.createContext({
logged_in: false
});
export default AuthContext;
LayoutContext.js
import React from "react";
const LayoutContext = React.createContext({
show_loading: false
});
export default LayoutContext;
LoadingScreen.js
import React from "react";
import LayoutContext from "./LayoutContext";
class LoadingScreen extends React.Component {
render() {
return (
<LayoutContext.Consumer>
{layout =>
layout.show_loading ? (
<div id="loading">
<div id="loading-center">
<div className="sk-chasing-dots">
<div className="sk-child sk-dot1"></div>
<div className="sk-child sk-dot2"></div>
</div>
</div>
</div>
) : null
}
</LayoutContext.Consumer>
);
}
}
export default LoadingScreen;
Following the example, I never really understood how this.props (in App.js) could hold my different contexts.
Both auth and layout show up as undefined, this.props is empty, which will in turn cause my app to throw errors such as Cannot read property 'show_loading' of undefined
I immediately liked the example provided in the React documentation, but I can't get this to work.
I've made a small snippet to show you how you could structure your context providers and consumers.
My App component in this case is the root of the app. It has all the providers, along with the value for each one of them. I am not changing this value, but I could if I wanted to.
This then has a single child component, MyOutsideComponent, containing all the chained consumers. There are better ways to do this, I just wanted to show you, one by one, how chaining consumers work. In practice you can neatly reduce this using a few techniques.
This MyOutsideComponent has the actual component, MyComponent, which takes all the context elements and just puts their value on the page. Nothing fancy, the point was to show how the values get passed.
let FirstContext = React.createContext('first');
let SecondContext = React.createContext('second');
let ThirdContext = React.createContext('third');
let FourthContext = React.createContext('fourth');
let MyComponent = (props) => {
return (<span >{Object.values(props).join(" ")}</span>);
};
let App = (props) => {
return (
<FirstContext.Provider value="this is">
<SecondContext.Provider value="how you">
<ThirdContext.Provider value="pass context">
<FourthContext.Provider value="around">
<MyOutsideComponent />
</FourthContext.Provider>
</ThirdContext.Provider>
</SecondContext.Provider>
</FirstContext.Provider>
);
};
let MyOutsideComponent = () => {
return ( < FirstContext.Consumer >
{first =>
(< SecondContext.Consumer >
{second =>
(< ThirdContext.Consumer >
{third =>
(<FourthContext.Consumer >
{fourth =>
(<MyComponent first={first} second={second} third={third} fourth={fourth} />)
}
</FourthContext.Consumer>)
}
</ThirdContext.Consumer>)
}
</SecondContext.Consumer>)
}
</FirstContext.Consumer>);
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Now, for the actual explanation. createContext gives you two actual components: a Provider and Consumer. This Provider, as you found out, has the value. The Consumer takes as child a single function taking one argument, which is your context's value.
This is where the docs are a bit unclear, and a bit which I hope I can help a bit. This does not get passed automatically in props unless the Provider is the direct parent of the component. You have to do it yourself. So, in the example above, I chained four consumers and then lined them all up in the props of my component.
You've asked about class-based components, this is how it ends up looking like:
let FirstContext = React.createContext('first');
let SecondContext = React.createContext('second');
let ThirdContext = React.createContext('third');
let FourthContext = React.createContext('fourth');
class MyComponent extends React.Component {
render() {
return ( < span > {Object.values(this.props).join(" ")} < /span>);
}
}
class App extends React.Component {
render() {
return (
<FirstContext.Provider value = "this is" >
<SecondContext.Provider value = "how you" >
<ThirdContext.Provider value = "pass context" >
<FourthContext.Provider value = "around" >
<MyOutsideComponent / >
</FourthContext.Provider>
</ThirdContext.Provider >
</SecondContext.Provider>
</FirstContext.Provider >
);
}
}
class MyOutsideComponent extends React.Component {
render() {
return (
<FirstContext.Consumer >
{ first =>
(< SecondContext.Consumer >
{ second =>
( < ThirdContext.Consumer >
{ third =>
( < FourthContext.Consumer >
{ fourth =>
( < MyComponent first = {first} second={second} third={third} fourth={fourth} />)
}
</FourthContext.Consumer>)
}
</ThirdContext.Consumer>)
}
</SecondContext.Consumer>)
}
</FirstContext.Consumer>
);
}
}
ReactDOM.render( < App / > , document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app" />