Search code examples
reactjsreact-context

Improve React-Context structure


I'm in the beginning of learning Reactjs and I am searching for some tips and tricks on how to improve following code structure (For now I'm only using sample data as values for the different states):

import { useState, createContext } from "react"

export const UserContext = createContext()

export const UserProvider = ({ children }) => {
    const [uuid, setUuid] = useState("5498cdec-2bfb-455c-adc6-d59825adde71")
    const [email, setEmail] = useState("[email protected]")
    const [username, setUsername] = useState("asdf1414")
    const [rank, setRank] = useState("ADMIN")
    const [profilePic, setProfilePic] = useState({ mime: "image/png", data: "" })
    const [joined, setJoined] = useState(Date.now())
    const [lastJoined, setLastJoined] = useState(Date.now())

    const value = {
        uuid: uuid,
        setUuid: setUuid,
        email: email,
        setEmail: setEmail,
        username: username,
        setUsername: setUsername,
        rank: rank,
        setRank: setRank,
        profilePic: profilePic,
        setProfilePic: setProfilePic,
        joined: joined,
        setJoined: setJoined,
        lastJoined: lastJoined,
        setLastJoined: setLastJoined
    }
    
    return (
        <UserContext.Provider value={value}>
            {children}
        </UserContext.Provider>
    )
}

My goal with this context is as follows: After successful log-in, all the data is fetched from the database and put into this context. Obviously I want to use and update the data from all over the webapp - therefore I provide the Context with the variable value.

My current "thorn in the eye" is, that the value variable is pretty stuffed and I have to manually type in all the data and update-functions. Is there a way I can simplify the value variable? Is there any best practice on how to do what I want to achieve?

Thanks in advance!

Kind Regards, Andreas


Solution

  • Thanks for the kick-off to think different about my problem - I figured out a way to improve the code structure as follows:

    import { useState, createContext } from "react"
    
    export const UserContext = createContext()
    
    export const UserProvider = ({ children }) => {
        const initValues = {
            uuid: "5498cdec-2bfb-455c-adc6-d59825adde71",
            email: "[email protected]",
            username: "asdf1414",
            rank: "ADMIN",
            profilePic: { mime: "image/png", data: "" },
            joined: Date.now(),
            last_joined: Date.now()
        }
        const [user, setUser] = useState(initValues)
    
        const changeUser = ([type, value]) => {
            setUser(prevValues => {
                return {...prevValues, [type]: value}
            })
        }
    
        const value = [user, changeUser]
        
        return (
            <UserContext.Provider value={value}>
                {children}
            </UserContext.Provider>
        )
    }
    

    The code above basically initialises the user-state with the initValues object, as proposed from Ron B. In order to change values from the state the function changeUser takes in an array of type and value basically being the key and value for the value in the object you want to update and returning the new state with the spreaded old object and assigning the new value by the provided key.