I'm trying to use toString to temporarily output a class to the DOM.
I'm getting some behaviour I don't understand where the overriden toString()
will always output the initial state. However, if an external function is used (i.e. stateToString) or even JSON.stringify
, the updated state is outputted as I would expect.
Below is my attempt to minimally reproduce this behaviour.
To reiterate, my expected behaviour is for all of them to initially output: ["initial"]
, which they do. However, the toString()
output does not update when the button is clicked but the other two do.
This seems particularly strange as stateToString
and State.toString
seem to be essentially identical functions, except one takes state as a receiver and one takes state as a parameter.
I'd appreciate if someone could explain why this behaviour occurs.
import React, { useReducer } from 'react';
class State {
constructor(xs) { this.xs = xs }
toString = () => `[${this.xs}]`
}
const stateToString = state => `[${state.xs}]`;
const reducer = (state, action) => ({
...state,
xs: [...state.xs, action.x]
});
const App = () => {
const [state, dispatch] = useReducer(reducer, new State(["initial"]));
return (
<div>
<button onClick={() => dispatch({ x: Math.random() })}>click</button><br />
toString: {state.toString()}<br />
print: {stateToString(state)}<br />
stringify: {JSON.stringify(state)}
</div>
);
};
export default App;