# Managing State Link for this heading Intermediate As your application grows, it helps to be more intentional about how your state is organized and how the data flows between your components. Redundant or duplicate state is a common source of bugs. In this chapter, you’ll learn how to structure your state well, how to keep your state update logic maintainable, and how to share state between distant components. ### In this chapter - How to think about UI changes as state changes - How to structure state well - How to “lift state up” to share it between components - How to control whether the state gets preserved or reset - How to consolidate complex state logic in a function - How to pass information without “prop drilling” - How to scale state management as your app grows ## Reacting to input with state Link for Reacting to input with state With React, you won’t modify the UI from code directly. For example, you won’t write commands like “disable the button”, “enable the button”, “show the success message”, etc. Instead, you will describe the UI you want to see for the different visual states of your component (“initial state”, “typing state”, “success state”), and then trigger the state changes in response to user input. This is similar to how designers think about UI. Here is a quiz form built using React. Note how it uses the `status` state variable to determine whether to enable or disable the submit button, and whether to show the success message instead. App.js App.js Download ResetFork 99 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import{useState}from'react'; exportdefaultfunctionForm(){ const\[answer,setAnswer\] = useState(''); const\[error,setError\] = useState(null); const\[status,setStatus\] = useState('typing'); if(status === 'success'){ return<h1>That's right!</h1> } asyncfunctionhandleSubmit(e){ e.preventDefault(); setStatus('submitting'); try{ awaitsubmitForm(answer); setStatus('success'); }catch(err){ setStatus('typing'); setError(err); } } functionhandleTextareaChange(e){ setAnswer(e.target.value); } return( <> <h2>City quiz</h2> <p> In which city is there a billboard that turns air into drinkable water? </p> <formonSubmit={handleSubmit}> <textarea value={answer} onChange={handleTextareaChange} disabled={status === 'submitting'} /> <br/> <buttondisabled={ answer.length === 0 \|\| status === 'submitting' }> Submit </button> {error !== null && <pclassName="Error"> {error.message} </p> } </form> </> ); } functionsubmitForm(answer){ // Pretend it's hitting the network. returnnewPromise((resolve,reject)=>{ setTimeout(()=>{ letshouldError = answer.toLowerCase() !== 'lima' if(shouldError){ reject(newError('Good guess but a wrong answer. Try again!')); }else{ resolve(); } },1500); }); } Sandpack Preview ## City quiz In which city is there a billboard that turns air into drinkable water? Submit Open on CodeSandboxOpen Sandbox Show more ## Ready to learn this topic? Read **Reacting to Input with State** to learn how to approach interactions with a state-driven mindset. Read More * * * ## Choosing the state structure Link for Choosing the state structure Structuring state well can make a difference between a component that is pleasant to modify and debug, and one that is a constant source of bugs. The most important principle is that state shouldn’t contain redundant or duplicated information. If there’s unnecessary state, it’s easy to forget to update it, and introduce bugs! For example, this form has a **redundant** `fullName` state variable: App.js App.js Download ResetFork ``` import { useState } from 'react'; export default function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [fullName, setFullName] = useState(''); function handleFirstNameChange(e) { setFirstName(e.target.value); setFullName(e.target.value + ' ' + lastName); } function handleLastNameChange(e) { setLastName(e.target.value); setFullName(firstName + ' ' + e.target.value); } return ( <> <h2>Let’s check you in</h2> <label> First name:{' '} <input value={firstName} onChange={handleFirstNameChange} /> </label> <label> Last name:{' '} <input value={lastName} onChange={handleLastNameChange} /> </label> <p> Your ticket will be issued to: <b>{fullName}</b> </p> </> ); } ``` Sandpack Preview Show more You can remove it and simplify the code by calculating `fullName` while the component is rendering: App.js App.js Download ResetFork ``` import { useState } from 'react'; export default function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const fullName = firstName + ' ' + lastName; function handleFirstNameChange(e) { setFirstName(e.target.value); } function handleLastNameChange(e) { setLastName(e.target.value); } return ( <> <h2>Let’s check you in</h2> <label> First name:{' '} <input value={firstName} onChange={handleFirstNameChange} /> </label> <label> Last name:{' '} <input value={lastName} onChange={handleLastNameChange} /> </label> <p> Your ticket will be issued to: <b>{fullName}</b> </p> </> ); } ``` Sandpack Preview Show more This might seem like a small change, but many bugs in React apps are fixed this way. ## Ready to learn this topic? Read **Choosing the State Structure** to learn how to design the state shape to avoid bugs. Read More * * *