我使用有效的用户名和密码登录。
导航栏更改为欢迎用户和注销导航链接按钮。
单击导航左上角的主页或刷新页面会丢失用户对象,导航栏会读取登录和注册,即使用户未明确注销
如何使用 react hooks 修复状态管理,如示例中所示,而不使用诸如 localstorage、cookies、Auth0 等替代方法?
App.js
import './App.css';
import React, { useState, Component, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Route, Switch, Redirect } from "react-router-dom";
import { LinkContainer } from "react-router-bootstrap";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import axios from 'axios'
import Home from "./containers/Home";
import Login from "./containers/Login";
import Signup from "./containers/Signup";
import Rooms from './containers/Rooms';
import RoomShow from './containers/RoomShow';
import UserContext from './context/UserContext'
function App() {
const [user, setUser] = useState(null);
const [allChannels, setAllChannels] = useState([]);
const [currentChannel, setCurrentChannel] = useState([]);
const handleLogin = (data) => {
setUser({
user: data
});
fetch('/channels')
.then(response => response.json())
.then(result => {
setAllChannels(result);
})
};
const handleLogout = () => {
setUser(null);
};
const getRoomData = (id) => {
fetch(`/rooms/${id}`)
.then(response => response.json())
.then(result => {
setCurrentChannel(
{
room: result.data,
users: result.data.attributes.users,
messages: result.data.attributes.messages
}
)
})
};
const subscribeToRoom = (event) => {
const room_id = event.target.id
user ? (this.postFirstMessage(room_id)) : (alert('You must be logged in to subscribe to a room.'))
};
const postFirstMessage = (roomId) => {
window.history.pushState(null, null, `/rooms/${roomId}`)
const message = {
content: `${this.state.currentUser.attributes.username} has joined this room!`,
user_id: this.state.user.id,
channel_id: roomId
}
fetch("/messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify({message: message})
})
.then(resp => resp.json())
.then(result => {
})
};
return (
<UserContext.Provider value={user, setUser}>
<div className="App container py-3">
<Navbar collapseOnSelect bg="light" expand="md" className="mb-3">
<Navbar.Brand href="/" className="font-weight-bold text-muted">
Chat
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse className="justify-content-end">
<Nav activeKey={window.location.pathname}>
{user ? (
<>
<Navbar.Text> Welcome, USER </Navbar.Text>
<Nav.Item><Nav.Link onClick={handleLogout}>Logout</Nav.Link>
</Nav.Item>
</>
) : (
<>
<LinkContainer to="/signup">
<Nav.Link>Signup</Nav.Link>
</LinkContainer>
<LinkContainer to="/login">
<Nav.Link>Login</Nav.Link>
</LinkContainer>
</>
)}
</Nav>
</Navbar.Collapse>
</Navbar>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/login"
// props such as props.history
// props.history.push used to redirection https://reactrouter.com/web/api/history
render={ (props) => (<Login
{...props}
handleLogin={handleLogin} />) } />
<Route exact path="/signup"
render={ (props) => (<Signup
{...props}
handleLogin={handleLogin} />) } />
<Route exact path='/rooms'
render={ (props) => (<Rooms />) } />
<Route exact path='/rooms/:id'
render={ (props) => {
return user ? (<RoomShow {...props}
cableApp={this.props.cableApp}
getRoomData={this.getRoomData}
updateApp={this.updateAppStateRoom}
roomData={this.state.currentRoom}
currentUser={this.state.user.data}
/>
) : (
<Redirect to='/rooms' />
)
}} />
</Switch>
</div>
</UserContext.Provider>
);
}
export default App;
容器/Login.js
import "./Login.css";
import axios from 'axios'
import React, { useState } from "react";
import { Link } from 'react-router-dom'
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import UserContext from '../context/UserContext'
function Login(props){
const [login, setLogin] = useState({username: null, password: null, errors: null})
const handleChange = (event) => {
const {name, value} = event.target
setLogin({
...login,
[name]: value
})
};
const handleSubmit = (event) => {
event.preventDefault()
const {username, password} = login
let user = {
username: username,
password: password
}
axios.post('/login', {user}, {withCredentials: true})
.then(response => {
if (response.data.logged_in) {
props.handleLogin(response.data)
redirect();
} else {
handleErrors();
console.log('response errors:', response.data.errors)
setLogin({
...login,
errors: response.data.errors
})
}
})
.catch(error => {
handleErrors();
console.log('api errors:', error)
})
};
const redirect = () => {
props.history.push('/')
}
const handleErrors = () => {
};
return (
<div className="Login">
<Form onSubmit={handleSubmit}>
<Form.Group size="lg" controlId="username">
<Form.Label>Username</Form.Label>
<Form.Control
autoFocus
type="text"
name="username"
onChange={handleChange}
/>
</Form.Group>
<Form.Group size="lg" controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
name="password"
onChange={handleChange}
/>
</Form.Group>
<Button block size="lg" type="submit">
Login
</Button>
<div>
or <Link to='/signup'>sign up</Link>
</div>
</Form>
</div>
);
}
export default Login;
容器/Home.js
import React from "react";
import "./Home.css";
export default function Home() {
return (
<div className="Home">
<div className="lander">
<h1>Chat</h1>
<p className="text-muted">A simple chat application</p>
</div>
</div>
);
}
上下文/UserContext.js
import React from 'react'
const UserContext = React.createContext(null)
export default UserContext
注意:
我之前在多个孩子上使用过 <UserContext.Consumer/>
但由于错误而省略了
TypeError: render is not a function