How to make a self-controlled button in react

Controlling how the buttons in your app can be sometimes redundant and you find yourself writing the same code to do the same stuff many times, what if you can have your own component that can decide for itself, how to render and how to behave.

In …


This content originally appeared on DEV Community and was authored by Omar Diaaeldine Elwakeel

Button image

Controlling how the buttons in your app can be sometimes redundant and you find yourself writing the same code to do the same stuff many times, what if you can have your own component that can decide for itself, how to render and how to behave.

In this tutorial I will show you how to have a generic button that can take care of itself according to the variables around it, like the current authenticated user and upon it decides how will it look and whether it will be enabled or disabled.

For this tutorial and for the sake of having a good insight on how helpful its, I'm going to build a slightly complicated app, I will use redux for the local state management, you will know why shortly.

If you want to follow along, please be my guest. But if you want to see the code you can go to the github repo.

let's create an app with create-react-app and name it as you like, after that we need to install some packages like react-redux @reduxjs/toolkit and optionally you can install @mui/material @mui/styles @emotion/react @emotion/styled

Inside the src directory we can have 2 folders one for the components and the other for the redux store

inside src/store/authSlice.js

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const login = createAsyncThunk(
    'app/auth/login',
    async (credentials) => {
        return credentials;
    }
);

export const logout = createAsyncThunk(
    'app/auth/logout',
    async () => {
        return null;
    }
);

const authSlice = createSlice({
    name: 'app/auth',
    initialState: null,
    extraReducers:{
        [login.fulfilled] : (state, action) => action.payload,
        [logout.fulfilled] : (state, action) => action.payload
    }
});

export default authSlice.reducer;

inside src/store/index.js

import { combineReducers, configureStore } from '@reduxjs/toolkit';
import auth from './authSlice';

const reducer = combineReducers({
    auth
})

const store = configureStore({
    reducer,
    middleware: getDefaultMiddleware =>
        getDefaultMiddleware({
            immutableCheck: false,
            serializableCheck: false
        }),
    devTools: process.env.NODE_ENV === 'development'
});

export default store;

these couple of files to configure the store for local state management, specifically the auth and current user signed in. we will wrap the application with the redux provider component and pass the store as props.

inside src/App.js

import { useState } from "react";
import { Provider } from 'react-redux';

import store from './store/index'

import Toolbar from "./components/Toolbar";
import AuthButton from "./components/AuthButton";

function App() {
  const [auth, setAuth] = useState('');

  return (
    <Provider store={store}>
      <div className="App">
        <Toolbar setAuth={setAuth}/>
        <AuthButton auth={auth}/>
      </div>
    </Provider>
  );
}

export default App;

for the Toolbar and the AuthButton components

inside src/components/Toolbar.js

import { Button, TextField } from "@mui/material";
import { makeStyles } from "@mui/styles";
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { login, logout } from "../store/authSlice";

const useStyles = makeStyles(() => ({
    container:{
        display:'flex',
        justifyContent:'center',
        alignItems:'center'
    }
}))

const employees = [
    {username:'marie', role:'ceo'}, 
    {username:'jack', role:'manager'}, 
    {username:'laila', role:'employee'}, 
    {username:'sam', role:'guest'}
]

export default function Toolbar({ setAuth }){
    const classes = useStyles();
    const dispatch = useDispatch();

    const [username, setUsername] = useState('')

    const handleLogin = () => {
        const credentials = employees.find(employee => employee.username === username)

        if(!credentials) return;

        dispatch(login(credentials))
    }

    const handleLogout = () => {
        dispatch(logout())
    }

    return (
        <div className={classes.container}>
            <TextField 
                onChange={(e) => setUsername(e.target.value)}
            />
            <Button onClick={(e) => handleLogin()}>Login</Button>
            <Button onClick={(e) => handleLogout()}>Logout</Button>
        </div>
    )
}

Now whenever we logout or login the button will be notified with the current authenticated user, and will fetch the role of the user and update itself, whether the color, disabled, etc.

inside src/components/AuthButton.js

import React from "react";
import { makeStyles } from "@mui/styles";
import { blue, green, orange, red } from "@mui/material/colors";
import { useSelector } from "react-redux";

const useStyles = makeStyles(() => {
    return {
        btn: {
            backgroundColor:({auth}) => {
                if(auth){
                    switch (auth) {
                        case "ceo":
                            return green[700]
                        case "manager":
                            return orange[700]
                        case "employee":
                            return blue[700]
                        default:
                            return red[700]
                    }
                }

                return red[700]
            },
            width:'20em',
            height:'5em',
            borderRadius:'5px',
            color:'white'
        }
    }
})

export default function AuthButton({ unauthorizedRoles }){
    const auth = useSelector(({auth}) => auth);
    const classes = useStyles({auth: auth?.role || ''});

    const isDisabled = unauthorizedRoles.includes(auth?.role)

    const renderMessage = () => {
        if(auth){
            if(!isDisabled){
                return `Hi, ${auth?.username} Want to do something cool`
            }
            else{
                return `Hi, ${auth?.username}, Sorry but you are not authorized for the cool stuff`
            }
        }

        return 'Why dont you login'
    }

    return (
        <button 
            variant="contained" 
            disabled={isDisabled} 
            className={classes.btn}
            >
            {renderMessage()}
        </button>    
    )
}

AuthButton.defaultProps = {
    unauthorizedRoles : ["guest"]
}

once you login or logout, the button will adjust itself accordingly.

Result


This content originally appeared on DEV Community and was authored by Omar Diaaeldine Elwakeel


Print Share Comment Cite Upload Translate Updates
APA

Omar Diaaeldine Elwakeel | Sciencx (2022-01-20T10:18:08+00:00) How to make a self-controlled button in react. Retrieved from https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/

MLA
" » How to make a self-controlled button in react." Omar Diaaeldine Elwakeel | Sciencx - Thursday January 20, 2022, https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/
HARVARD
Omar Diaaeldine Elwakeel | Sciencx Thursday January 20, 2022 » How to make a self-controlled button in react., viewed ,<https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/>
VANCOUVER
Omar Diaaeldine Elwakeel | Sciencx - » How to make a self-controlled button in react. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/
CHICAGO
" » How to make a self-controlled button in react." Omar Diaaeldine Elwakeel | Sciencx - Accessed . https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/
IEEE
" » How to make a self-controlled button in react." Omar Diaaeldine Elwakeel | Sciencx [Online]. Available: https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/. [Accessed: ]
rf:citation
» How to make a self-controlled button in react | Omar Diaaeldine Elwakeel | Sciencx | https://www.scien.cx/2022/01/20/how-to-make-a-self-controlled-button-in-react/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.