react-konva: React Konva doesn't work with React 16.3 Context API
I am trying to use React 16.3 Context API based on render props with React Konva:
import React from "react";
import { Layer, Stage, Circle, Group, Line } from "react-konva";
const { Consumer, Provider } = React.createContext({ width: 0, height: 0 });
const ToolsLayer = () => (
<Consumer>
{({ height, width }) => (
<Layer>
<Group offsetY={-height} y={-42}>
<Line
points={[0, 0, width, 0, width, 42, 0, 42]}
closed
stroke="black"
/>
<Circle radius={11} fill="red" stroke="black" x={21} y={21} />
<Circle radius={11} fill="green" stroke="black" x={21 + 42} y={21} />
<Group />
</Group>
</Layer>
)}
</Consumer>
);
export default function Canvas({
width = window.innerWidth,
height = window.innerHeight
}) {
return (
<Provider value={{ width, height }}>
<Stage width={width} height={height}>
<ToolsLayer />
</Stage>
</Provider>
);
}
And I get runtime error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `ToolsLayer`.
Reproducible demo: https://codesandbox.io/s/2o9j1r6l30
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 13
- Comments: 26 (7 by maintainers)
Demo how to “bridge” contexts into
react-konva
tree:https://codesandbox.io/s/ykqw8r4r21
The usage of context api should probably be an example on the offical docs site, there is no mention there of this problem/pitfall and I only found this due to some google searches (which first led me in other directions).
Update on this issue. From
react-konva@18.2.2
, context bridge should work by default. It will be really cool if someone can try it and provide feedback.@lyleunderwood Thanks! I actually had implemented it in such a way for the
<Stage>
, but was also using the<Html>
component from react-konva-utils, which requires a second bridge. So I mistakenly thought it wasn’t bridging correctly.Similarly for MUI we should be able to do something like:
I encountered this issue with my project. After playing with it, I realize that we can skip the bridge by declaring the context consumer inside
Stage
. So something like this will work just fine.https://codesandbox.io/s/react-konva-consume-context-demo-d5yht
@Guria basically facebook/react#13728 is an API change which will make the necessity of re-introducing your context into the hierarchy at a point below the point at which the context barrier happens (the
Stage
in the example of react-konva) less ugly. So instead of:you have:
Because facebook/react#13728 doesn’t implement any kind of introspection of context solution, I don’t think that it offers a fix that react-konva could implement, and I think that https://github.com/facebook/react/issues/13332 would be a potential direction for solving that problem.
Does this sound about right @gaearon ?
Maybe allowing for something like this:
Which would transport context into the reconciler tree. The root component that still belongs to the dom (
Stage
in konvas case) could provide the subscribeContext function, which adds a dom-tied context into a list and returns a new context that provides changes values into the reconciler tree.This is still broken on v1.7.2. You can see in the reproducible demo linked above that it’s picking up the default value defined by the initial creation of the context (
{width: 0, height: 0}
) rather than the values provided by Provider.