4

I am attempting to create a login page where a user presses a button, and the state is updated using useContext. I have followed a few tutorials online and did my rounds looking for an explanation or solution to no avail. The issue I am running into currently is the compiler is saying in login_spotify.tsx the property setUser does not exist on type 'User'. What would be suggested for me to update the state with the new one in login_spotify.tsx.

Hopefully, my program will grow and become more complex, so instead of just passing the props down, useContext will be needed.

My code is as follows:

app.tsx

import React, { useState } from 'react';
import './App.css';

import { UserContext } from '../Context';
import { User} from '../Types';

import { defaultUser } from '../../constants/defaults';
import { SpotifyLoginButton } from '../Buttons';

function App() {
    const [ user, setUser ] = useState<User>(defaultUser);
    return (
        <div className="window">
            <h1>{user.name}</h1>
            < UserContext.Provider value={{user, setUser}}>
                <SpotifyLoginButton />
            </UserContext.Provider>
        </div>
    );
}

export default App;

user_context.tsx

import { createContext } from "react";

import { defaultUser } from "../../constants/defaults";

const UserContext = createContext(defaultUser);

export { UserContext }

login_spotify.tsx

import React, { useContext } from "react";
import Button from '@material-ui/core/Button';
import { UserContext } from "../Context";

function SpotifyLoginButton() {

    const {user, setUser} = useContext(UserContext);

    return (
        <Button variant={"outlined"} 
                color={'primary'} 
                onClick={() => { 
                    setUser({
                        email: "[email protected]",
                        image: "something",
                        name: "Jane Doe",
                        tokens: {
                            accessToken: "abc123",
                            refreshToken: "def234",
                        },
                    });
                }}>
            Login with Spotify
        </Button>
    );
}

export default SpotifyLoginButton

types.tsx

export type User  ={
    email: string | null;
    image: string | null;
    name: string | null;
    tokens: {
        accessToken: string | null;
        refreshToken: string | null;
    };
}

defaults.tsx

import { User } from '../components/Types';

// default user
export const defaultUser: User = {
    email: null,
    image: null,
    name: null,
    tokens: {
        accessToken: null,
        refreshToken: null,
    },
};

1 Answer 1

6

you should init the setUser function when creating context

const UserContext = createContext({
    user: defaultUser,
    setUser: (user: User) => {}
})
Sign up to request clarification or add additional context in comments.

3 Comments

This is the right answer. The context is not just a user object, it also has a setter function. So setting these defaults infers the correct type for the context.
Thank you for this!
Is there any other way to do it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.