Using a React Context With React-konva
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
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.
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.