I'm new to React, ionic, tsx, etc. and I've seen a lot of stackoverflow and tutorials but can't find anything that I can transfer to my setup.
I'm trying to set a state in a class component to provide to child components so that they can use the useState hook to access a variable so that they can update the render after using setState in another component. Basically, I'm trying to get the login button in an IonHeader to authenticate the user using firebase. The component can then update the state via setState using the onAuthStateChanged hook. Other components in the IonContent can then use useState to get the callback and display their content or not, depending on whether the user is logged in or not. I might need to bind the class instance to the setState function so that children can access the function and state?
The problem I'm trying to solve is to synchronize states that individual child components can listen to and modify to alert other components to render with the new state. For the auth and db objects I can put them into their respective components.
I will replace "test: String" with the user from auth, if null then it will be an object. This way I can check if the user is logged in or not. It's all wrapped up 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's going wrong here, I wrapped the return into just one element and provided the child props via PropsWithChildren. If I add text inside the LoginButton I get "Type '{children: string; }' is missing the following properties from type 'States': db, auth, test". If I add any element in it the error message changes, so how can I add any child component in it? I think PropsWithChildren will solve this problem for me!
Not sure if this is a good solution or if it works, any feedback is appreciated!
The reason why
"Type '{}'
etc. is displayed is because thestate
field inherits fromReact.Component
By default,this. state
is of typeReadonly
, and when you expand it like{...this.state}
> the result is of type{}
.Your use of
as States
does not change the type ofthis.state
. This is similar to how inlet A: Superclass = B as Subclass
, the type ofA
will be Superclass, not Subclass.One way to solve the input problem is to override the type of the
state
field.Another approach is to explicitly specify the type parameters of the generic
React.Component
, whereP
represents props andS
code> is used state.