Skip to main content

Tutorial with react-redux - Person Name

This tutorial shows tiny example code with react-redux. There are two variants. The first one is with useSelector. The second one is with useTrackedSelector.

With useSelector

import * as React from 'react';
import { useState } from 'react';
import { createStore } from 'redux';
import { Provider, useDispatch, useSelector } from 'react-redux';

const initialState = {
firstName: 'React',
lastName: 'Tracked',
};

const reducer = (state = initialState, action) => {
switch (action.type) {
case 'setFirstName':
return { ...state, firstName: action.firstName };
case 'setLastName':
return { ...state, lastName: action.lastName };
default:
return state;
}
};

const store = createStore(reducer);

const EditPerson = () => {
const dispatch = useDispatch();
const firstName = useSelector((state) => state.firstName);
const lastName = useSelector((state) => state.lastName);
const setFirstName = (e) => {
const firstName = e.target.value;
dispatch({ type: 'setFirstName', firstName });
};
const setLastName = (e) => {
const lastName = e.target.value;
dispatch({ type: 'setLastName', lastName });
};
return (
<div>
<div>
First Name:
<input value={firstName} onChange={setFirstName} />
</div>
<div>
Last Name:
<input value={lastName} onChange={setLastName} />
</div>
</div>
);
};

const ShowPerson = () => {
const [onlyFirstName, setOnlyFirstName] = useState(false);
const firstName = useSelector((state) => state.firstName);
const lastName = useSelector((state) =>
onlyFirstName ? null : state.lastName,
);
return (
<div>
<button type="button" onClick={() => setOnlyFirstName((s) => !s)}>
{onlyFirstName ? 'Showing only first name' : 'Showing full name'}
</button>
{onlyFirstName ? (
<div>First Name: {firstName}</div>
) : (
<div>
Full Name: {firstName} {lastName}
</div>
)}
</div>
);
};

const App = () => {
return (
<Provider store={store}>
<EditPerson />
<ShowPerson />
</Provider>
);
};

export default App;

It's a bit tricky to make a selector conditional.

CodeSandbox

With useTrackedSelector

import * as React from 'react';
import { useState } from 'react';
import { createStore } from 'redux';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { createTrackedSelector } from 'react-tracked';

const initialState = {
firstName: 'React',
lastName: 'Tracked',
};

const reducer = (state = initialState, action) => {
switch (action.type) {
case 'setFirstName':
return { ...state, firstName: action.firstName };
case 'setLastName':
return { ...state, lastName: action.lastName };
default:
return state;
}
};

const store = createStore(reducer);

const useTrackedSelector = createTrackedSelector(useSelector);

const EditPerson = () => {
const dispatch = useDispatch();
const state = useTrackedSelector();
const setFirstName = (e) => {
const firstName = e.target.value;
dispatch({ type: 'setFirstName', firstName });
};
const setLastName = (e) => {
const lastName = e.target.value;
dispatch({ type: 'setLastName', lastName });
};
return (
<div>
<div>
First Name:
<input value={state.firstName} onChange={setFirstName} />
</div>
<div>
Last Name:
<input value={state.lastName} onChange={setLastName} />
</div>
</div>
);
};

const ShowPerson = () => {
const state = useTrackedSelector();
const [onlyFirstName, setOnlyFirstName] = useState(false);
return (
<div>
<button type="button" onClick={() => setOnlyFirstName((s) => !s)}>
{onlyFirstName ? 'Showing only first name' : 'Showing full name'}
</button>
{onlyFirstName ? (
<div>First Name: {state.firstName}</div>
) : (
<div>
Full Name: {state.firstName} {state.lastName}
</div>
)}
</div>
);
};

const App = () => {
return (
<Provider store={store}>
<EditPerson />
<ShowPerson />
</Provider>
);
};

export default App;

This works just the same without the tricky selector.

CodeSandbox