Reputation: 14961
see here:
https://codesandbox.io/s/nervous-hermann-5wsph
basically:
they keyboard used in the example, seems to get a wrong copy of the state
it fixes once you press shift on the keyboard. But other than that? the keyboard onKeyPress has the wrong useState
variables.
what is the problem?
the debug text is supposed to change IN THE CONSOLE, but doesn't. That means whatever I fire onKeyPress will have the wrong copy of the state variables except the ones I call in the callback.
That is just very very bad. I thought useState
will solve those problems, not make them harder ?! Am I missing something?
Upvotes: 1
Views: 307
Reputation: 2964
The issue is not with React state but with the Keyboard
component.
react-simple-keyboard
does not realize that props have changed, so the onKeyPress
function that you pass it always has the initial value.
When React state changes (the debug text), your onKeyPressed
function in the MyComponent
component will be recreated with the new values. In turn, the onKeyPress
function inside your KeyboardWrapper
also gets recreated.
This new function gets passed as a prop to Keyboard
, but in the source code for Keyboard
(see here) a check is performed to see whether the props have changed.
The function that performs this check can be found here:
export const propsChanged = (prevProps, props) => {
const cleanProps = sourceObj =>
JSON.stringify({
...sourceObj,
stateToIgnore: null
});
return cleanProps(props) !== cleanProps(prevProps);
};
This function has a bug. When the props are 'cleaned', all functions are removed - which is a bit silly, since a function is a valid prop.
So the previous props (which includes your old onKeyPress
function with the initial value of debugText
) is 'cleaned' and compared with the new 'cleaned' props, and it looks to the Keyboard
that the props have not changed, since neither the previous clean
props or new clean
props, have the onKeyPress
function.
I added some logging to that function:
const previousProps = {
onKeyPress: () => {
console.log("Initial text");
},
};
const newProps = {
onKeyPress: () => {
console.log("New text");
},
};
const propsChanged = (prevProps, props) => {
const cleanProps = (sourceObj) =>
JSON.stringify({
...sourceObj,
stateToIgnore: null,
});
console.log("original prev props:", prevProps);
console.log("clean prev props:", cleanProps(prevProps));
console.log("original new props:", props);
console.log("clean new props:", cleanProps(props));
return cleanProps(props) !== cleanProps(prevProps);
};
console.log(
"does keyboard think props have changed?",
propsChanged(previousProps, newProps)
);
console.log("have props actually changed?", previousProps !== newProps);
console.log("is there a bug with react-simple-keyboard?", true);
and here is the result:
original prev props: { onKeyPress: [Function: onKeyPress] }
clean prev props: {"stateToIgnore":null}
original new props: { onKeyPress: [Function: onKeyPress] }
clean new props: {"stateToIgnore":null}
does keyboard think props have changed? false
have props actually changed? true
is there a bug with react-simple-keyboard? true
I suggest filing an issue over on their github repo.
Upvotes: 3