State Management across Visual and YAML Editor

Ishant Mehta
Harness Engineering
3 min readOct 8, 2022

What is YAML

YAML is a human-readable data serialization language used for configuration files in order to store data. It is widely used by many programming languages like Java, Python, and GoLang and as a configuration language by Kubernetes, Docker Compose, Ansible, etc.

JSON vs YAML: YAML is easily readable by humans and is expressive, extensible and easy to implement and use.
YAML is easily readable by humans and is expressive, extensible and easy to implement and use.

Harness is a developer-friendly tool. Users can configure their entities(including services, pipelines, and environments) using YAML or Visual modes(UI). A user can copy their existing YAML configuration and use it at Harness.

Problem statement

  1. How do we keep the Visual and YAML states in sync with each other
  2. We want to render the Discard button (only when we have some changes)
Visual Mode — Showing different tabs, Save, Discard button
Visual Mode — Showing different Tabs, UnsavedChanges, Save, Discard button
YAML Mode — Showing YAML Editor

State Management

We want one single state that is the source of truth. For this, we use the React Context API and use a single state at the dashboard level.

Components can read the state at any point in time and dispatch an action to update the entity state using the useReducer hook.

Visual Mode

This mode has 3 tabs, namely, Overview, Configuration, and Schedule.

Each tab reads the context state and, using this, creates its own initial state. This then uses Formik Form to render the form fields with initial values.

On the change of a field value, it dispatches an action to update the entity in the dashboard context. We use debounced updates here to improve the performance.

YAML Mode

This mode renders a react-monaco-editor, which needs a stringified version of the object. This uses a “dump” function from the js-yaml library and stringifies the object, which is then passed to the Editor.

How do we update when the user changes some text in the YAML editor

We have 2 options here,

  1. Dispatch an action on every keystroke. This sounds expensive.
  2. Use a set interval to dispatch an action

We use a setInterval of 1000ms and check whether something has been updated or not. We use yamlRef to get the current state of the editor and compare it with the context state. If it's updated, we dispatch an action to update it.

Discard Button / Unsaved Changes

A user is editing a configuration when she realizes she wants to undo the changes. She can use the discard button to undo them.

For the discard and save buttons to get enabled, we need to know if there is an update. If there are no updates, these buttons are disabled.

For this, we use another state object, named oldEntity, and use the isEqual method from lodash to perform a deep comparison between the old and current state objects.

If she clicks on the discard button, we restore the initial state, by setting the current state object equal to the oldEntity object.

Join Harness community on slack to speak to our engineering team

--

--