ایجاد یک سایت چند قالبی (دارک و لایت) در ری اکت

بعد از مدت ها برگشتم . این بار با یک ویدئو .

دوست داشتم که تجربه ایجاد یک سایت با دو قالب دارک و لایت و نحوه پیاده سازی اون رو در ری اکت با هم کار کنیم .

خوب قبل از اینکه ویدئو رو ببیند کمی صحبت کنیم

طبق علاقه شخصی خودم و دلایل منطقی (یا حتی غیر منطقی و تعصبی) از context api استفاده کردم. در کنار اون ، متریال رو نصب کردم (material-ui نسخه 4.2) که با پروایدری که داره بتونیم قالب رو کامل تغییر بدیم . خوب توی این راه به مشکلاتی خوردم ، چون هنوز داکیومنت جدید متریال رو کامل نخوندم و به همین دلیل در تابع createMuiTheme به مشکلاتی خوردم و برطرف کردم .

ممنون میشم نظرتون رو بدونم

کد فایل ها رو بعد از فیلم قرار دادم .
https://www.aparat.com/v/eEPAX


state.js

import React, {createContext, useContext, useReducer} from 'react';

export const StateContext = createContext();

export const StateProvider = ({reducer, initialState, children}) =>(
    <StateContext.Provider value={useReducer(reducer, initialState)}>
        {children}
    </StateContext.Provider>
);

export const useStateValue = () => useContext(StateContext);

MaterialUIProvider.js

import {createMuiTheme} from '@material-ui/core/styles';
import purple from '@material-ui/core/colors/purple';
import green from '@material-ui/core/colors/green';

const primary = green[500];
const accent = purple['A200'];

const light = {
    primary: {
        main: primary
    },
    secondary: {
        main: accent
    },
}

const dark = {
    primary: {
        main: accent
    },
    secondary: {
        main: primary
    },
}

export const lightTheme = createMuiTheme({
    palette: light,
});

export const darkTheme = createMuiTheme({
    palette: dark,
});

Login.js

import React, {useEffect} from 'react';
import Avatar from '@material-ui/core/Avatar';
import Button from '@material-ui/core/Button';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import Link from '@material-ui/core/Link';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import Typography from '@material-ui/core/Typography';
import {makeStyles} from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import LightButton from "@material-ui/icons/Highlight"
import DarkButton from "@material-ui/icons/HighlightOutlined"
import {useStateValue} from "./state";
import IconButton from "@material-ui/core/IconButton/IconButton";

function MadeWithLove() {
    return (
        <Typography variant="body2" color="textSecondary" align="center">
            {'Built with love by the '}
            <Link color="inherit" href="https://material-ui.com/">
                Material-UI
            </Link>
            {' team.'}
        </Typography>
    );
}

const useStyles = makeStyles(theme => ({
    '@global': {
        body: {
            backgroundColor: theme.palette.common.white,
        },
    },
    paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
    },
    avatar: {
        margin: theme.spacing(1),
        backgroundColor: theme.palette.secondary.main,
    },
    form: {
        width: '100%', // Fix IE 11 issue.
        marginTop: theme.spacing(1),
    },
    submit: {
        margin: theme.spacing(3, 0, 2),
    },
}));

export default function SignIn() {
    const classes = useStyles();
    const [{theme}, dispatch] = useStateValue();

    return (
        <Container component="main" maxWidth="xs">
            <CssBaseline/>

            <div className={classes.paper}>
                {theme === "light" &&
                <IconButton
                    ={() => {
                        dispatch({
                            type: "changeTheme",
                            theme: "dark"
                        })
                    }}>
                    <LightButton/>
                </IconButton>
                }

                {theme === "dark" &&
                <IconButton
                    ={() => {
                        dispatch({
                            type: "changeTheme",
                            theme: "light"
                        })
                    }}>
                    <DarkButton/>
                </IconButton>
                }
                <Avatar className={classes.avatar}>
                    <LockOutlinedIcon/>
                </Avatar>
                <Typography component="h1" variant="h5">
                    Sign in
                </Typography>
                <form className={classes.form} noValidate>
                    <TextField
                        variant="outlined"
                        margin="normal"
                        required
                        fullWidth
                        id="email"
                        label="Email Address"
                        name="email"
                        autoComplete="email"
                        autoFocus
                    />
                    <TextField
                        variant="outlined"
                        margin="normal"
                        required
                        fullWidth
                        name="password"
                        label="Password"
                        type="password"
                        id="password"
                        autoComplete="current-password"
                    />
                    <FormControlLabel
                        control={<Checkbox value="remember" color="primary"/>}
                        label="Remember me"
                    />
                    <Button
                        type="submit"
                        fullWidth
                        variant="contained"
                        color="primary"
                        className={classes.submit}
                    >
                        Sign In
                    </Button>
                    <Grid container>
                        <Grid item xs>
                            <Link href="#" variant="body2">
                                Forgot password?
                            </Link>
                        </Grid>
                        <Grid item>
                            <Link href="#" variant="body2">
                                {"Don't have an account? Sign Up"}
                            </Link>
                        </Grid>
                    </Grid>
                </form>
            </div>
            <Box mt={5}>
                <MadeWithLove/>
            </Box>
        </Container>
    );
}

App.js

import React from 'react';
import Login from "./Login";
import {StateContext, StateProvider} from "./state";
import {darkTheme, lightTheme} from "./MaterialUIProvider";
import {ThemeProvider} from '@material-ui/styles';

export default function SignIn() {

    const initialState = {
        theme: 'light'
    }

    const reducer = (state, action) => {
        switch (action.type) {
            case 'changeTheme':
                return {
                    ...state,
                    theme: action.theme
                };

            default:
                return state;
        }
    };

    return (
        <StateProvider initialState={initialState} reducer={reducer}>
            <StateContext.Consumer>
                {value=> {
                    const theme=value[0].theme

                    return (
                        <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
                            <Login/>
                        </ThemeProvider>
                    )
                }
                }
            </StateContext.Consumer>
        </StateProvider>
    );
}