Reacting to Input with State Flashcards
Reacting to in put with state
React uses a declarative way to manipulate the UI.
Instead of manipulating individual pieces of the UI directly, you describe the different states that your component can be in, and switch between them in response to the user input.
Thinking about UI declaratively
- Identify your component’s different visual states
- Determine what triggers those state changes
- Represent the state in memory using useState
- Remove any non-essential state variables
- Connect the event handlers to set the state
Step 1: Identify your component’s different visual states
First, you need to visualize all the different “states” of the UI the user might see:
- Empty: Form has a disabled “Submit” button.
- Typing: Form has an enabled “Submit” button.
- Submitting: Form is completely disabled. Spinner is shown.
- Success: “Thank you” message is shown instead of a form.
- Error: Same as Typing state, but with an extra error message.
Just like a designer, you’ll want to “mock up” or create “mocks” for the different states before you add logic.
Mocking lets you quickly iterate on the UI before you wire up any logic.
Step 2: Determine what triggers those state changes
You can trigger state updates in response to two kinds of inputs:
- Human inputs, like clicking a button, typing in a field, navigating a link.
- Computer inputs, like a network response arriving, a timeout completing, an image loading.
In both cases, you must set state variables to update the UI. For the form you’re developing, you will need to change state in response to a few different inputs:
- Changing the text input (human) should switch it from the Empty state to the Typing state or back, depending on whether the text box is empty or not.
- Clicking the Submit button (human) should switch it to the Submitting state.
- Successful network response (computer) should switch it to the Success state.
- Failed network response (computer) should switch it to the Error state with the matching error message.
Human inputs often require event handlers
Step 3: Represent the state in memory with useState
Next you’ll need to represent the visual states of your component in memory with useState.
Simplicity is key: each piece of state is a “moving piece”, and you want as few “moving pieces” as possible. More complexity leads to more bugs
Start with the state that absolutely must be there.
Then, you’ll need a state variable representing which one of the visual states described earlier you want to display.
There’s usually more than a single way to represent that in memory, so you’ll need to experiment with it.
If you struggle to think of the best way immediately, start by adding enough state that you’re definitely sure that all the possible visual states are covered.
Your first idea likely won’t be the best, but that’s ok—refactoring state is a part of the process
Step 4: Remove any non-essential state variables
You want to avoid duplication in the state content so you’re only tracking what is essential.
Spending a little time on refactoring your state structure will make your components easier to understand, reduce duplication, and avoid unintended meanings.
Your goal is to prevent the cases where the state in memory doesn’t represent any valid UI that you’d want a user to see.
Does this state cause a paradox? For example, isTyping and isSubmitting can’t both be true. A paradox usually means that the state is not constrained enough. There are four possible combinations of two booleans, but only three correspond to valid states.
To remove the “impossible” state, you can combine these into a status that must be one of three values: ‘typing’, ‘submitting’, or ‘success’.
Is the same information available in another state variable already? Another paradox: isEmpty and isTyping can’t be true at the same time. By making them separate state variables, you risk them going out of sync and causing bugs.
Fortunately, you can remove isEmpty and instead check answer.length === 0.
Can you get the same information from the inverse of another state variable? isError is not needed because you can check error !== null instead.
Step 5: Connect the event handlers to set state
Lastly, create event handlers to set the state variables.