Merhaba, bu yazımda basit bir uygulama ile react içerisinde login mantığı nasıl kurgulanır, bunu anlatacağım.
Oturum açma ve Kullanıcı Profili ekranları oluşturacağız. Örnek bir webapi üzerinden işlemlerimizi gerçekleştireceğiz.
- Method: POST
- URL: https://www.fatihsoysal.com/api/login (Dikkat: URL örnek için verilmiştir.)
- Body (JSON):
1 2 3 4 | { "username": "info@fatihsoysal.com", "password": "testpass" } |
Geri dönüş(response) ise şu şekilde olduğunu düşünelim:
1 2 3 4 5 6 7 8 9 10 11 12 13 | { "status": "ok", "message": "Logged in", "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": 1, "fname": "Fatih", "lname": "Soysal", "username": "info@fatihsoysal.com", "email": "info@fatihsoysal.com", "avatar": "https://www.fatihsoysal.com/users/1.png" } } |
Gereklilikler:
- Node.js https://nodejs.org
- Yarn
1 2 | npm install --global yarn |
Kurulum için bir test react projesi oluşturalım:
1 2 | npx create-react-app react-basic-login |
Kurulum gerçekleştirdik, şimdi çalışma klasörünü açalım:
1 2 | cd react-basic-login |
Kullanacağımız paket kurulumlarını gerçekleştirelim:
- Material UI
- react-router-dom
- Sweetalert
1 2 | yarn add @material-ui/core @material-ui/icons react-router-dom sweetalert |
Oturum Açma ve Profil için ekranlar oluşturalım
2 ekran oluşturacağız:
- Oturum açma API’sinin kullanıldığı oturum açma sayfası için Sigin.js
- Kullanıcı profilini görüntülemek için Profile.js (bu ekrana gitmeden önce oturum açmış olmanız gerekecek)
SignIn.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | import React, { useState } 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 Paper from '@material-ui/core/Paper'; import Grid from '@material-ui/core/Grid'; import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import swal from 'sweetalert'; const useStyles = makeStyles((theme) => ({ root: { height: '100vh', }, image: { backgroundImage: 'url(https://source.unsplash.com/random)', backgroundSize: 'cover', }, paper: { margin: theme.spacing(8, 4), display: 'flex', flexDirection: 'column', alignItems: 'center', }, avatar: { margin: theme.spacing(1), backgroundColor: theme.palette.secondary.main, }, form: { width: '100%', marginTop: theme.spacing(1), }, submit: { margin: theme.spacing(3, 0, 2), }, })); async function loginUser(credentials) { return fetch('https://www.mecallapi.com/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }) .then(data => data.json()) } export default function Signin() { const classes = useStyles(); const [username, setUserName] = useState(); const [password, setPassword] = useState(); const handleSubmit = async e => { e.preventDefault(); const response = await loginUser({ username, password }); if ('accessToken' in response) { swal("Success", response.message, "success", { buttons: false, timer: 2000, }) .then((value) => { localStorage.setItem('accessToken', response['accessToken']); localStorage.setItem('user', JSON.stringify(response['user'])); window.location.href = "/profile"; }); } else { swal("Failed", response.message, "error"); } } return ( <Grid container className={classes.root}> <CssBaseline /> <Grid item xs={false} md={7} className={classes.image} /> <Grid item xs={12} md={5} component={Paper} elevation={6} square> <div className={classes.paper}> <Avatar className={classes.avatar}> <LockOutlinedIcon /> </Avatar> <Typography component="h1" variant="h5"> Sign in </Typography> <form className={classes.form} noValidate onSubmit={handleSubmit}> <TextField variant="outlined" margin="normal" required fullWidth id="email" name="email" label="Email Address" onChange={e => setUserName(e.target.value)} /> <TextField variant="outlined" margin="normal" required fullWidth id="password" name="password" label="Password" type="password" onChange={e => setPassword(e.target.value)} /> <Button type="submit" fullWidth variant="contained" color="primary" className={classes.submit} > Sign In </Button> </form> </div> </Grid> </Grid> ); } |
Profile.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import IconButton from '@material-ui/core/IconButton'; import MenuItem from '@material-ui/core/MenuItem'; import Menu from '@material-ui/core/Menu'; import Avatar from '@material-ui/core/Avatar'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; const useStyles = makeStyles((theme) => ({ root: { flexGrow: 1, }, menuButton: { marginRight: theme.spacing(2), }, title: { flexGrow: 1, }, large: { width: theme.spacing(20), height: theme.spacing(20), }, })); export default function Profile() { const classes = useStyles(); const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const user = JSON.parse(localStorage.getItem('user')); const handleMenu = (event) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const handleLogout = () => { localStorage.removeItem("accessToken"); localStorage.removeItem("user"); window.location.href = "/"; }; return ( <div className={classes.root}> <AppBar position="static"> <Toolbar> <Typography variant="h6" className={classes.title}> Profile </Typography> <div> <IconButton onClick={handleMenu} color="inherit"> <Avatar src={user.avatar} /> </IconButton> <Menu id="menu-appbar" anchorEl={anchorEl} open={open} onClose={handleClose} > <MenuItem onClick={handleLogout}>Logout</MenuItem> </Menu> </div> </Toolbar> </AppBar> <Card className={classes.root} variant="outlined"> <CardContent> <Avatar src={user.avatar} className={classes.large} /> <Typography variant="h5"> Welcome {user.fname} {user.lname} </Typography> </CardContent> </Card> </div> ); } |
Son olarak, Oturum Açma ve Profil ekranları arasındaki yönlendirme için App.js’yi düzenleyin . Oturum açma API’sinin çağrılmasında erişim belirteci yoksa kullanıcı yalnızca Oturum açma ekranına erişebilecektir .
app.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import React from 'react'; import './App.css'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import Signin from './Signin'; import Profile from './Profile'; function App() { const token = localStorage.getItem('accessToken'); if(!token) { return <Signin /> } return ( <div className="wrapper"> <BrowserRouter> <Switch> <Route path="/profile"> <Profile /> </Route> <Route path="/"> <Profile /> </Route> </Switch> </BrowserRouter> </div> ); } export default App; |
İşlemler bu kadar, şimdi uygulamayı başlatalım:
1 2 | yarn start |
İşlem başarılı görünüyor! Bu makalemizde react üzerinde basit bir login işlemi ve session kontrolü nasıl yapılır, bunu inceledik, bir sonraki makalede görüşmek üzere, kendinize iyi bakın.