React observing

Quick start

Quick start

This page explains how to get started with React observing. You will learn how to build your first observable state and integrate with React.


Simple input

Let's get started by creating a observable state.

Here we are going to call our state NameStore, because it is being shared among more files. But you can name it whatever you like.

1// ./NameStore.ts
2
3import { observe } from 'react-observing'
4
5export NameStore = observe('some text');

Now let's use the state in an input component with one of the available hooks. useObserver allows you to retrieve the state and change it if necessary.

This hook is very similar to react's useState hook.

1// ./Component1.tsx
2
3import React from 'react'
4import { useObserver } from 'react-observing'
5
6import { NameStore } from './NameStore'
7
8export const Component1 = () => {
9 const [name, setName] = useObserver(NameStore)
10
11 return (
12 <input
13 value={name}
14 placeholder="Type your name"
15 onChange={e => setName(e.target.value)}
16 />
17 )
18}

Having created the input component, let's use the component twice. Note that the result will be that when you update the name in one component, the second will also be updated.

This happens because when updating the value in the NameStore all components that are on screen with a useObserver are listening for state changes.

1// ./App.tsx
2
3import React from 'react'
4
5import { Component1 } from './Component1'
6
7export const App = () => {
8
9 return (
10 <>
11 <Component1 />
12 <Component1 />
13 </>
14 )
15}

Properties as states

Let's get started by creating a object with observable properties.

To work correctly all properties that are States must be mandatory. See more

1// ./NameAndLastNameStore.ts
2
3import { observe } from 'react-observing'
4
5export NameAndLastNameStore = {
6 name: observe('Juca'),
7 lastName: observe('Foo')
8};

Now let's create two input components, one will be linked to the first name and the other to the last name.

1// ./Inputs.tsx
2
3import React from 'react'
4import { useObserver } from 'react-observing'
5
6import { NameAndLastNameStore } from './NameAndLastNameStore'
7
8export const InputName = () => {
9 const [name, setName] = useObserver(NameAndLastNameStore.name)
10
11 return <input
12 value={name}
13 onChange={e => setName(e.target.value)}
14 />
15}
16
17export const InputLastName = () => {
18 const [lastName, setLastName] = useObserver(NameAndLastNameStore.lastName)
19
20 return <input
21 value={lastName}
22 onChange={e => setLastName(e.target.value)}
23 />
24}

Now, when we change the input values, only the input that has the link to the property will be re-rendered.

The NameAndLastNameStore object could be a state too, and in the App we would have a useObserver on the object. In this scenario, you would have to pass properties that are state as props in the input components.

1// ./App.tsx
2
3import React from 'react'
4
5import { InputName, InputLastName } from './Inputs'
6
7export const App = () => {
8
9 return (
10 <>
11 <InputName />
12 <InputLastName />
13 </>
14 )
15}

Array of states

react-observing works very well with lists of states.

In react, you normally create a state which is an array, and to update a specific item of that array you are required to update the entire array.

Below see how your application can be much more performant with the list of states.

Here we will create a list, which is a state, which contains several states of type string.

1// ./NamesStore.ts
2
3import { observe } from 'react-observing'
4
5export NamesStore = observe([
6 observe('Juca'),
7 observe('Pedro'),
8 observe('Paulo'),
9]);

See that here we are going to create an input component, which must receive as prop a state of type string. It is no longer necessary to access the store directly, but if necessary it is still possible.

1// ./Input.tsx
2
3import React from 'react'
4import { useObserver, IObservable } from 'react-observing'
5
6interface IInputProps {
7 name: IObservable<string>;
8}
9export const Input: React.FC<IInputProps> = ({ name }) => {
10 const [name, setName] = useObserver(name)
11
12 return <input
13 value={name}
14 onChange={e => setName(e.target.value)}
15 />
16}

Here we are going to use useObserver on our store and map the array to a list of the Input component we created.

In this scenario, when we change the value of any input on the screen, we will generate a re-render only on the components that depend on that state. The other components generated by our mapping will not suffer any kind of effect.

1// ./App.tsx
2
3import React from 'react'
4import { useObserver } from 'react-observing'
5
6import { NamesStore } from './NamesStore'
7import { Input } from './Input'
8
9export const App = () => {
10 const [names, setNames] = useObserver(NamesStore)
11
12 return (
13 <>
14 {names.map(name => <Input name={name} />)}
15 </>
16 )
17}
Edit this page on GitHub