Using a React Context With React-konva
— JavaScript, Software Development — 2 min read
Following on from my post on using react-konva
as part of reciprocal.dev to build a User Journey Map and then adding zoom and panning to said map I decided to add some enhancements to change properties of components rendered on the canvas from outside the canvas.
In order to implement this enhancement I needed to introduce an app-wide state so I could track both the interaction in the non-canvas UI and update the value in the canvas components.
To do this I started by building a context that I could then access, using the useContext
hook in the components that needed to access the properties the context exposed to change the app’s state.
I added the context provider at the root component level so child components could access the context and while this worked well with the UI elements I had created to display the screen information, it didn’t work with the components in the canvas.
The components that were children of the Stage
used to render canvas elements were unable to access these properties due to scoping issues.
Accessing the React Context within a react-konva Stage
The fix for getting around the scoping issue is relatively simple, it just requires setting up another context provider inside the Stage
.
For the new provider to re-use the value from the original provider we need to wrap a consumer around the Stage
and make sure that our context provider component can have it’s value set by a prop.
Once we have the provider inside the Stage
we can the use the useContext
hook within the components that will be rendered to the canvas.
The final structure looks like this:
Using the React Context to update UI elements on state change
With the context accessible from inside the canvas we can use this context to update a shared state between UI elements outside of the canvas and those inside of it.
Firstly we need to have some means of getting and setting a value that will be updated via the non-canvas UI. To do this we use useState
to track a value called colour
and the getter and setter of this value to the provider via it’s value prop.
This colour value is changed inside of the non-canvas UI we call setColour
whenever the user selects a value from the colour select element.
Within the canvas components we take the colour
value from the context and use it to set the colour used in the component.
Once we’ve got the colour value being read by the canvas component and set by the non-canvas component we can now set the colour of the Rect
using the select box.
Summary
While this post covers a very simple use case there’s no reason why you couldn’t use a React Context to track the state of a number of values and build an advanced UI that allows the user to update objects within the canvas from outside of it.