The global store provided by Redux is convenient. Any component that is in the hierarchy under Provider
can reach out and grab the state it needs. But you don't want to become overzealous and make all state global. The state that you put in the global store should satisfy both of the these criteria:
With this in mind, you decide to add a component named Adder
that contains a form for adding a new quotation to the store. Initially the component is a jumble of input elements:
export function Adder() {
return (
<div id="adder-panel" className="panel">
<label htmlFor="author-input">Author</label>
<input id="author-input" type="text" />
<label htmlFor="text-input">Quotation</label>
<textarea id="text-input" />
<button>Add</button>
</div>
);
}
In JSX, the for
attribute on labels is renamed htmlFor
to prevent collision with the for
keyword in JavaScript.
In a moment, you will organize these elements in a grid using a stylesheet. You define this component in src/Adder.js
and add it to your App
component:
function App() {
return (
<div className="App">
<Authors />
<Quotations />
<Adder />
</div>
);
}
While the user is filling out the form, the input is not yet ready to go in the global store. But you still need the input to persist. If you haven't saved the input anywhere, it will be lost if the component is re-rendered.
Local state is a good candidate for persisting intermediate form input. You declare local state for both the author and the quotation using the useState
function:
import {useState} from 'react';
export function Adder() {
const [author, setAuthor] = useState('');
const [text, setText] = useState('');
// ...
}
As you did in the color palette app, you populate the form elements using this state and update it on change events:
export function Adder() {
// ...
return (
<div id="adder-panel" className="panel">
<label htmlFor="author-input">Author</label>
<input
id="author-input"
type="text"
value={author}
onChange={event => setAuthor(event.target.value)}
/>
<label htmlFor="text-input">Quotation</label>
<textarea
id="text-input"
value={text}
onChange={event => setText(event.target.value)}
/>
<button>Add</button>
</div>
);
}
Only when the user clicks Add do you want to push the author and text into the global store. Before you make that happen, you decide to add some styling to clean up the interface.