Introduction to Jotai. Derived atoms. Controlling UI
Tags: javascript, webdev, react, beginners
Published: 2022-09-25 18:59:16

[Intro to Jotai. Part 1](https://dev.to/fricze/introduction-to-jotai-from-react-hooks-to-jotai-atoms-3nmd)
[Intro to Jotai. Part 2](https://dev.to/fricze/introduction-to-jotai-derived-atoms-data-validation-mdb)

Creating derived atoms is easy and useful. From one data source you can create many atoms. They allow to transform source data, or create new information based on it. Derived atoms are your first tool to structure your data models, and to control your UI state.

You already created simple form with one input and validation. Now let’s add another input with validation and submit button. Later, we can use validation atoms to decide whether user can submit the form. In this part, you’ll also switch from bare HTML elements to Material UI.

```javascript
import TextField from "@mui/material/TextField";

const Input = ({ type = "text", label, sourceAtom }: InputProps) => {
  const [text, setText] = useAtom(sourceAtom);
  return (
    <TextField
      type={type}
      label={label}
      variant="filled"
      value={text}
      onChange={(e) => setText(e.target.value)}
    />
  );
};
```

Let’s use new version of `Input` component and create inputs for name and password.

```javascript
const nameAtom = atom("John");
const passwordAtom = atom("");

const Form = () => {
  return (
    <Box
      component="form"
      sx={{
        "& > :not(style)": { m: 2, width: "25ch" }
      }}
    >
      <Typography variant="h3" gutterBottom>
        Registration form
      </Typography>

      <Input label="Name" sourceAtom={nameAtom} />
      <Input type="password" label="Password" sourceAtom={passwordAtom} />
    </Box>
  );
};
```

Source atoms are ready. Next step is creating derived validation atoms.

```javascript
const nameLengthAtom = atom((get) => get(nameAtom).length);
const passwordLengthAtom = atom((get) => get(passwordAtom).length);

const isNameValid = atom((get) => get(nameLengthAtom) >= 3);
const isPasswordValid = atom((get) => get(passwordLengthAtom) >= 3);
```

Because you want to control whether user can submit a form we need one more atom. It’s a general atom describing whether whole form is in valid state.

```javascript
const isFormValid = atom((get) => get(isNameValid) && get(isPasswordValid));
```

This atom derives values from name and password validation atoms and joins those values together. Using this new atom you’re ready to create submit button.

```javascript
const SubmitButton = () => {
  const isValid = useAtomValue(isFormValid);

  return (
    <Box>
      <Button disabled={!isValid} variant="outlined">
        Register
      </Button>
    </Box>
  );
};
```

If form is valid submit button is ready to click. If form is invalid button is disabled. Simple.

Let’s see how full form looks now.

```javascript
const Form = () => (
  <Box
    component="form"
    sx={{
      "& > :not(style)": { m: 2, width: "25ch" }
    }}
  >
    <Typography variant="h3" gutterBottom>
      Registration form
    </Typography>

    <Input label="Name" sourceAtom={nameAtom} />
    <Input type="password" label="Password" sourceAtom={passwordAtom} />

    <Error sourceAtom={isNameValid} errorInfo="Name is too short" />
    <Error sourceAtom={isPasswordValid} errorInfo="Password is too short" />

    <SubmitButton />
  </Box>
);
```

This form also uses new, general `Error` component to display particular errors. Check out [full code](https://codesandbox.io/s/gallant-chaum-z9ze23?file=/src/App.tsx) to see source of this component.

As always check out [Jotai website](https://jotai.org/) for docs and more examples of Jotai code.