Skip to main content

State management in the Editor Starter

State in the Editor Starter is managed with the built-in React state management utilities: useState() and useContext().

Why?

The Editor Starter was built in a way that as many different teams can adopt it as easily as possible.

While the default React state management utilities are controversial for some, any React application can make use of them and developers are most familiar with them.

Shape

The whole state of the Editor Starter is stored in a single object with the shape defined by the EditorState.

src/editor/state/types.ts
ts
export type UndoableState = {
tracks: TrackType[];
assets: Record<string, EditorStarterAsset>;
items: Record<string, EditorStarterItem>;
fps: number;
compositionWidth: number;
compositionHeight: number;
};
export type EditorState = {
undoableState: UndoableState;
selectedItems: string[];
textItemEditing: string | null;
textItemHoverPreview: TextItemHoverPreview | null;
rendering: RenderState;
captions: CaptionState;
initialized: boolean;
itemsBeingTrimmed: ItemBeingTrimmed[];
loop: boolean;
};
  • undoableState - State that is affected by the undo stack
    • tracks: An array of timeline tracks, the last ones are the ones rendered in the back.
    • assets: A map of all assets that have been uploaded to the editor.
    • items: A map of all items that have been added to the editor.
    • fps: The frame rate (kept in state, but no UI is exposed to change it)
    • compositionWidth: The width of the canvas
    • compositionHeight: The height of the canvas
  • selectedItems: An array of item IDs that are currently selected
  • textItemEditing: The ID of the text item that is currently being edited, if there is one
  • textItemHoverPreview: Preview updates of a text item (for example if a font is hovered in the font picker, the text will render temporarily with the font hovered)
  • rendering: The state of the rendering process
  • captions: The state of captioning process
  • initialized: Whether the editor has been initialized, if not initialized, canvas will not be visible
  • itemsBeingTrimmed: An array of items that are currently being trimmed, to show an indication of the maximum trim that is possible
  • loop: Whether the playback should loop

Undoable state

State is separated into undoable and non-undoable parts.
Undoable state is located within the undoableState object of the root state.

Undoable state may be:

  • Position, size and other properties of an item
  • Assets and tracks
  • Video properties like dimensions and frame rate

Non-undoable state may be:

  • Asset upload progress
  • Captioning progress
  • Zoom level
  • Rendering state
  • Selection state

See also: Undo and Redo

Contexts

In src/editor-context-provider.tsx, you will see a very deeply nested tree of various context providers.

This is intentional and achieves that when updating a portion of the state, only the components that are dependent on that portion of the state will re-render, while the rest of the components will not.

For the best performance, we recommend that you continue to use this pattern in your own application.

Preventing state updates when nothing has changed

You should prevent an unnecessary state update when nothing has changed.

Throughout the codebase, you will see checks that prevent an unnecessary state update.

Preventing an identity change
ts
export const markAsDragging = (state: EditorState, itemId: string): EditorState => {
return changeItem(state, itemId, (item) => {
if (item.isDragging) {
// The item would not change, so we return the original object
return item;
}
return {
...item,
isDragging: true,
};
});
};

Reading the state imperatively

If you only need to access the state upon an interaction, you can use the useCurrentStateAsRef() hook.
It allows you to imperatively access the state when you need it.

You cannot build a reactive UI with it, but is more performant than using a hook that re-renders when the state changes.

For example: A save button that only needs to access the state when the user clicks it.

See also