JotaiJotai

状態
Primitive and flexible state management for React

Initializing Atom State on Render

There are times when you need to create an reusable component which uses atoms.

These atoms' initial state are determined by the props passed to the component.

Below is a basic example of illustrating how you can use Provider and its prop, initialValues, to initialize state.

Basic Example

CodeSandbox link: codesandbox.

Consider a basic example where you have a reusable TextDisplay component that allows you to display and update plain text.

This component has two child components, PrettyText and UpdateTextInput.

  • PrettyText displays the text in blue.
  • UpdateTextInput is an input field which updates the text value.

As opposed to passing text as a prop in the two child components, you decided that the text state should be shared between components as an atom.

To make TextDisplay component reusable, we take in a prop initialTextValue, which determines the initial state of the text atom.

To tie initialTextValue to textAtom, we wrap the child components in a Provider. Then, we populate the initialValues array of atom tuples with the initial values.

const textAtom = atom('')
const PrettyText = () => {
const [text] = useAtom(textAtom)
return (
<>
<text
style={{
color: 'blue',
}}>
{text}
</text>
</>
)
}
const UpdateTextInput = () => {
const [text, setText] = useAtom(textAtom)
const handleInputChange = (e) => {
setText(e.target.value)
}
return (
<>
<input onChange={handleInputChange} value={text} />
</>
)
}
export const TextDisplay = ({ initialTextValue }) => {
return (
// initialising on state with prop on render here
<Provider initialValues={[[textAtom, initialTextValue]]}>
<PrettyText />
<br />
<UpdateTextInput />
</Provider>
)
}

Now, we can easily resue TextDisplay component with different initial text values despite them referencing the "same" atom.

export default function App() {
return (
<div className="App">
<TextDisplay initialTextValue="initial text value 1" />
<TextDisplay initialTextValue="initial text value 2" />
</div>
)
}

This behavior is due to our child components looking for the lowest commmon Provider ancestor to derive its value.

For more information on Provider behavior, please read the docs here.