Issue
I'm new to react, ionic, tsx and all that and I've looked at so many stackoverflow and tutorials but couldn't find anything to transfer to my setup.
I'm trying to set a state in a class component to give to child components so that they can access variables with useState hook so they can update render after setState was used in another component. Basically, I'm trying to get a login button in the IonHeader to authenticate user with firebase. This component can then make use of the onAuthStateChanged hook to update the state with setState. Then the other component in a IonContent can get a callback with useState and either display it's content or not depending if the user is logged in or not. I'll probably need to bind the class instance to the setState function so the child can access the function and state?
The problem I'm trying to solve is synchronizing a state that the separate children can listen to and modify to alert the other component to render with the new state. For the auth and db object I could put them in their respective components.
I'll be replacing the 'test: String' with user from auth, either it'll be an object if null. That way I can check if the user is logged in or not. This is all wrapped in IonReactRoute and
States.tsx
export interface States extends React.PropsWithChildren{
db: Firestore,
auth: Auth,
test: String,
}
Button.tsx
export const LoginButton: React.FC<States> = (children, props) =>
{
return (
<Fragment>
<div id='divLogin'>
<button>login {props.test}</button>
{props.children}
</div>
</Fragment>
)
}
Home.tsx
export default class Home extends React.Component{
constructor(props) {
super(props)
// init firebase app
initializeApp(firebaseConfig)
// init services
this.state = {
db: getFirestore(),
auth: getAuth(),
test: 'teststring'
} as States
}
render() {
return (
<IonPage>
{/* Header */}
<IonHeader translucent>
<IonToolbar>
<IonTitle>Hydroponics-lurvas777</IonTitle>
<LoginButton {...this.state}></LoginButton>
{/*^^^^ this gives error: "Type '{}' is missing the following properties from type 'States': db, auth, test"*/}
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
{/* Condense header for ios devices, larger to smaller header */}
<IonHeader collapse="condense" translucent>
<IonToolbar>
<IonTitle size="large">Hej ios</IonTitle>
</IonToolbar>
</IonHeader>
{/* Here's the real content, everything is toggles by auth state */}
</IonContent>
</IonPage>
);
}
};
I don't understand what is going wrong here, I've wrapped my return to only one element and provided children props through PropsWithChildren. If I add text inside the LoginButton I get "Type '{ children: string; }' is missing the following properties from type 'States': db, auth, test". The error messages changes if I add any elements inside, so how do I add any children components inside this? Thought PropsWithChildren would solve this for me!
Don't know if this is a good solution anyway, or if it'll work at all, any feedback is appreciated!
Solution
The reason why it says "Type '{}'
and so on is because the state
field was inherited from from React.Component
. By default, this.state
is typed as Readonly<{}>
, and when you spread it like {...this.state}
, the result is of type {}
.
Your usage of as States
didn't change the type of this.state
. This is comparable to how in let A: Superclass = B as Subclass
the type of A
will be Superclass, not Subclass.
One way to solve the typing problem is by overriding the type of the state
field.
export default class Home extends React.Component{
state: States
constructor(props: Props) {
...
}
...
}
Another way is by explicitly specifying the type parameters of the generic React.Component<P, S>
, where P
is for props and S
is for state.
export default class Home extends React.Component<Props, States>{
constructor(props: Props) {
...
}
...
}
Answered By - qrsngky
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.