Choosing the state structure

Group related states

This helps avoid you forgetting to update all the related states.

Just consider that you cant update just one value, without updating all places where the state is used.

const [position, setPosition] = useState({ x: 0, y: 0 })

Avoid contradictions

The below clearly has the possibility of contradicting, where both states are true.

const [isSending, setIsSending] = useState(false);
const [isSent, setIsSent] = useState(false);

Instead use a single state that holds a string.

const [status, setStatus] = useState('sending');

Avoid redundancy

Full name below is redundant since we can calculate it at runtime. So remove it.

const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [fullName, setFullName] = useState('');

Avoid duplication

In the following case we have a list of items and an item we have selected.

The selected item unnecessarily holds all information on the selected item.

items = [{ id: 0, title: 'pretzels'}, ...]
selectedItem = {id: 0, title: 'pretzels'}

Instead its better to have selected item use an Id.

Get all other info from items.

items = [{ id: 0, title: 'pretzels'}, ...]
selectedId = 0

As a side note, its a good idea for state to only hold information that you would want to update the UI with, not just all information.

Avoid deeply nested state

childPlaces: [{
    id: 1,
    title: 'Earth',
    childPlaces: [{
      id: 2,
      title: 'Africa',
      childPlaces: [{
        id: 3,
        title: 'Botswana',
        childPlaces: []
      }, {
        id: 4,
        title: 'Egypt',
        childPlaces: []
      },

export const initialTravelPlan = {
  0: {
    id: 0,
    title: '(Root)',
    childIds: [1, 42, 46],
  },
  1: {
    id: 1,
    title: 'Earth',
    childIds: [2, 10, 19, 26, 34]
  },
  2: {
    id: 2,
    title: 'Africa',
    childIds: [3, 4, 5, 6 , 7, 8, 9]
  },