Issue
Hi Stack Overflow Community,
I have the following object
const initialState = { count: 0, isOpen: false };
in which I want multiple class components i.e.
class Class1 extends React.Component <Props, State> {}
class Class2 extends React.Component <Props, State> {}
class Class3 extends React.Component <Props, State> {}
to be able to read or update any of the initialState
values. Does anyone know a way to do this?
I've tried using state-pool (as shown below) and react-hooks-global-state but they only work with a function component. This is the error message when using the first library in a class component:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
import * as React from "react";
import StatePool from 'state-pool';
const initialState = StatePool.createState({count: 0, isOpen: false});
interface Props {};
interface State {
isPlayButton: boolean,
};
export class Class1 extends React.Component <Props, State> {
constructor(props: any) {
super(props);
this.state = {
isPlayButton: true
};
const [state, setState] = StatePool.useState(initialState);
};
...
}
Solution
As @Phil mentioned, the React context allows data sharing in a component tree. You can share the state
and an update()
method by context.
On the consumer side(<Class1/>
, <Class2/>
, <Class3/>
), they can get the state
and update()
methods from the context.
import React, { FC } from 'react';
type State = { count: number; isOpen: boolean };
const SharedContext = React.createContext<{
state: State;
update(state: Partial<State>): void;
}>({
state: undefined,
update(state: Partial<State>) {},
});
class SharedContextProvider extends React.Component<
React.PropsWithChildren,
State
> {
state: State = { count: 0, isOpen: false };
render() {
return (
<SharedContext.Provider
value={{
state: this.state,
update: (newState: State) => this.setState(newState),
}}
>
{this.props.children}
</SharedContext.Provider>
);
}
}
class Class1 extends React.Component {
render() {
return (
<SharedContext.Consumer>
{(context) => {
return (
<div>
<div>count in class 1:{context.state.count}</div>
<button
onClick={() =>
context.update({ count: context.state.count + 1 })
}
>
increase in class 1
</button>
</div>
);
}}
</SharedContext.Consumer>
);
}
}
class Class2 extends React.Component {
render() {
return (
<SharedContext.Consumer>
{(context) => {
return (
<div>
<div>count in class 2:{context.state.count}</div>
<button
onClick={() =>
context.update({ count: context.state.count + 1 })
}
>
increase in class 2
</button>
</div>
);
}}
</SharedContext.Consumer>
);
}
}
class Class3 extends React.Component {
render() {
return (
<SharedContext.Consumer>
{(context) => {
return (
<div>
<div>count in class 3:{context.state.count}</div>
<button
onClick={() =>
context.update({ count: context.state.count + 1 })
}
>
increase in class 3
</button>
</div>
);
}}
</SharedContext.Consumer>
);
}
}
export const App = () => {
return (
<SharedContextProvider>
<Class1 />
<Class2 />
<Class3 />
</SharedContextProvider>
);
};
Answered By - Lin Du
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.