Conditional rendering
Answered
WhyFencePost posted this in #help-forum
I have a value of state, which updates properly, but i need a way to conditionally render different components based on state. State can change at any time. Every way I have tried fails.
What I have tried:
1.
2.
3.
Not one of those changes what is displayed when state changes, so what is the right way to do this? BTW state is a state, using
What I have tried:
1.
if (state == 0) {
return (
//Components here
);
}
2.
return (
{state == 0 && //Component here}
);
3.
return (
{state == 0 ? //Component here , //Other component here}
);
Not one of those changes what is displayed when state changes, so what is the right way to do this? BTW state is a state, using
useState()
Answered by WhyFencePost
I did some digging, and the issue seems to be related to something called
shallow equality
, which has to do with when an object re-renders (the state needs to be changed on the object itself it seems). I need to change it from the child, so i need a different way to force a re-render of this object when a child's state changes. To do this I needed to change the let state
to a useState
instead of a variable, making the component re-render on state change. Therefore my final code looks like this:function Login() {
const [pwString, setPwString] = useState("");
const [userString, setUserString] = useState("");
const [componentState, setComponentState] = useState(1); //NOTICE THE CHANGE HERE
useEffect(() => {
if (pwString != "") {
setComponentState(0);
//Login Logic
//Wait in debug and switch to 3
setComponentState(3); //debug
} else if (userString != "") {
setComponentState(0);
//Login Logic
//Wait in debug and switch to 2
setComponentState(2); //debug
}
}, [userString, pwString]);
return (
<>
<div className="w-screen h-screen">
{componentState == 1 ? <LoginPage1 setUserString={setUserString} userString={userString} /> : <h1>This is not one</h1>}
</div>
</>
);
}
3 Replies
Great golden digger wasp
Bro you third approach should work, the reason that it is not working because you make a syntax mistake in their.
I have created a example react app for you so you can better understand
If you have any question you can ask.
I have created a example react app for you so you can better understand
import { useState } from "react";
function App() {
const [state, setState] = useState(0);
return (
<>
<button
onClick={() => {
setState(state + 1);
}}>
Plus
</button>
<button
onClick={() => {
setState(state - 1);
}}>
Minus
</button>
<h1>{state}</h1>
{state == 1 ? <h1>1</h1> : <h1>This is not one</h1>}
</>
);
}
export default App;
If you have any question you can ask.
@Great golden digger wasp Bro you third approach should work, the reason that it is not working because you make a syntax mistake in their.
I have created a example react app for you so you can better understand
javascript
import { useState } from "react";
function App() {
const [state, setState] = useState(0);
return (
<>
<button
onClick={() => {
setState(state + 1);
}}>
Plus
</button>
<button
onClick={() => {
setState(state - 1);
}}>
Minus
</button>
<h1>{state}</h1>
{state == 1 ? <h1>1</h1> : <h1>This is not one</h1>}
</>
);
}
export default App;
If you have any question you can ask.
does not work, logging the state it updates, but the stuff that is shown does not:
The setState is in a child of this (the LoginPage1)
function Login() {
const [pwString, setPwString] = useState("");
const [userString, setUserString] = useState("");
let state = 1;
useEffect(() => {
if (pwString != "") {
state = 0;
//Login Logic
//Wait in debug and switch to 3
state = 3; //debug
} else if (userString != "") {
state = 0;
//Login Logic
//Wait in debug and switch to 2
state = 2; //debug
}
}, [userString, pwString]);
return (
<>
<div className="w-screen h-screen">
{state == 1 ? <LoginPage1 setUserString={setUserString} userString={userString} /> : <h1>This is not one</h1>}
</div>
</>
);
}
The setState is in a child of this (the LoginPage1)
I did some digging, and the issue seems to be related to something called
shallow equality
, which has to do with when an object re-renders (the state needs to be changed on the object itself it seems). I need to change it from the child, so i need a different way to force a re-render of this object when a child's state changes. To do this I needed to change the let state
to a useState
instead of a variable, making the component re-render on state change. Therefore my final code looks like this:function Login() {
const [pwString, setPwString] = useState("");
const [userString, setUserString] = useState("");
const [componentState, setComponentState] = useState(1); //NOTICE THE CHANGE HERE
useEffect(() => {
if (pwString != "") {
setComponentState(0);
//Login Logic
//Wait in debug and switch to 3
setComponentState(3); //debug
} else if (userString != "") {
setComponentState(0);
//Login Logic
//Wait in debug and switch to 2
setComponentState(2); //debug
}
}, [userString, pwString]);
return (
<>
<div className="w-screen h-screen">
{componentState == 1 ? <LoginPage1 setUserString={setUserString} userString={userString} /> : <h1>This is not one</h1>}
</div>
</>
);
}
Answer