So i am trying to lear about React contexts
and I am a bit confused. from its documentation:
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
So this means i can have the whole state of an app as global and i can update it from any child components , right?
However I am confused about how to go with it. I have a small app that shows either login, signup or Logged in screen to user based on their input. i am expecting that any of the following components should be able to change the value of global object stored in context, but i am unsure about how to go with it (mentioned the unsure functions as todos
)
// context
const MyAppSettings = React.createContext(
{
userId:null,
enableMarketing:false,
theme:"light"
}
)
//ui components(having access to local state as well as global context
function SettingsUI({onThemeChange,onConsentChange}){
let settings = useContext(MyAppSettings)
return(
<div>
<button onClick={e=>onThemeChange()}>Change Theme to {settings.theme==="light"?"dark":"light"}</button>
<br/>
<button onClick={e=>onConsentChange()}> {settings.enableMarketing?"withdraw consent for marketing emails":"give consent for marketing emails"}</button>
</div>
)
}
function Auth({onAuthClick}){
let settings = useContext(MyAppSettings)
let textColor = settings.theme==="light" ? "black" : "white"
let bg = settings.theme==="light"?"white": "brown"
let finalStyling= {border:"1px solid black",width:"200px",display:"block",marginBottom:"4px",backgroundColor:bg,color:textColor}
let [currentEmail,updateEmail] = useState("")
let emailUI = <input type="text" style={finalStyling} placeholder="email" value={currentEmail} onChange={e=>updateEmail(e.target.value)} />
let [currentPwd,updatePwd] = useState("")
let passwordUi = <input type="password" style={finalStyling} placeholder="password" value={currentPwd} onChange={e=>updatePwd(e.target.value)} />
let [currentName,updateName] = useState("")
let [isSignup,toggleSignUp ]= useState(false)
let nameUi = isSignup ? <input type="text" style={finalStyling} placeholder="name" value={currentName} onChange={e=>updateName(e.target.value)} /> : ""
let authBtnText = isSignup? "Sign up now!" : "Login now!"
let switchBtnText = isSignup? "Login Instead" : "Signup Instead"
function getCurrentInfo(){
return {
email:currentEmail,
pwd:currentPwd,
isUserSigningUp:isSignup,
name:currentName
}
}
return(
<>
{nameUi}
{emailUI}
{passwordUi}
<div>
<button onClick={e=>onAuthClick(getCurrentInfo())} >{authBtnText}</button>
<button onClick={e=>toggleSignUp(!isSignup)} >{switchBtnText}</button>
</div>
</>
)
}
function LoggedIn({logoutClick}){
let settings = useContext(MyAppSettings)
let textColor = settings.theme === "light" ? "black" : "white"
let bg = settings.theme === "light" ? "white" : "brown"
return (
<div style={{padding: "8px", backgroundColor: bg, color: textColor}}>
<p>You have successfully logged in. your user id is {settings.userId}</p>
<button onClick={e => logoutClick()}>logout</button>
</div>
)
}
//component controlling the other components and responsible for changing context values (TODO: HOW??)
function UserLoginSystem(){
let settings = useContext(MyAppSettings)
let onThemeChangeListener = ()=> {/*todo toggle theme settings to dark/light*/}
let onConsentChangeListener = ()=> {/*todo toggle theme consent settings*/}
let section1 = <SettingsUI onConsentChange={onConsentChangeListener} onThemeChange={onThemeChangeListener}/>
let onUserTryingToAuthenticate = (credsRequest)=>{/*todo set user to uuid if email/password match some static email pwd*/}
let section2Auth= <Auth onAuthClick={onUserTryingToAuthenticate}/>
let onUserTryingToLogout = ()=>{/*todo set user to null*/}
let section2LoggedIn = <LoggedIn logoutClick={onUserTryingToLogout}/>
return (
<div style={{width: "max-content", padding: "8px", border: "1px solid purple"}}>
<h1>using context apis</h1>
<div style={{width: "max-content", padding: "8px", border: "1px solid purple"}}>
{settings.userId!==null && section1}
{settings.userId === null ? section2Auth : section2LoggedIn}
</div>
</div>
)
}
// rendering user login system
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode> <UserLoginSystem/> </React.StrictMode>);
Screenshots: