login组件
在pages文件夹中新建一个login文件夹,然后是熟悉的index.js style.js store文件夹
import React, { PureComponent } from "react";
// import { actionCreator } from "./store";
import { connect } from "react-redux";
import { LoginWrapper} from "./style";
class Login extends PureComponent {
render() {
return (
<LoginWrapper>
Login
</LoginWrapper>
)
}
}
const mapStateToProps = (state) => ({
})
const mapDispatchToProps = (dispatch) => ({
})
export default connect(mapStateToProps, mapDispatchToProps)(Login);
App.js中引入
import Login from "./pages/login/index.js";
class App extends Component {
render() {
return (。。。。。。
<BrowserRouter>
<Header />。。。
<Route path="/login" exact component={Login}></Route>
。。。
</BrowserRouter>
</Provider>
);
}
}
export default App;
每增加一个reducer,就要记得来总store这里,补充一下
import { combineReducers } from "redux-immutable"
import { reducer as headReducer } from "../common/header/store"
import { reducer as homeReducer } from "../pages/home/store"
import { reducer as loginReducer } from "../pages/login/store"
//引入redux-immutable,使全局state变成immutable对象
const reducer= combineReducers({
header: headReducer,
home: homeReducer,
login: loginReducer
})
export default reducer;
修改header组件,如果已登录,显示"退出",否则显示“登录”
这就需要header组件获取到login下的数据
跳转到src/common/header/index.js文件,修改
render() {
const { ... , login } = this.props;
return(
{
login ? <Navitem className="right">退出登录</Navitem>:<Navitem className="right">登录</Navitem>
}
......
}
const mapStateToProps = (state) => {
return {
。。。。
login:state.getIn(["login","login"])
}
}
同时,还需要增加路由,以便用户点击登录时,能够跳转到登录页面
{
login ? <Navitem className="right">退出登录</Navitem>:
<Link to="/login"><Navitem className="right">登录</Navitem></Link>
}
Login组件的点击登录功能实现
src/pages/login/index.js
ref的作用,我很不熟悉
class Login extends PureComponent {
render() {
return (
<Input placeholder="账号" ref={(input)=>{this.account=input} }></Input>
!!!上面这句ref会把输入的内容赋值给this.account!!!
<Input placeholder="密码" type="password" ref={ (input)=>{this.password=input}}></Input>
!!!上面这句ref会把输入的内容赋值给this.password!!!
<Button onClick={()=>this.props.login(this.account,this.password)}>登录</Button>
!!!!一定记住,如果想传递参数,一定要用箭头函数的形式
)
}
}
const mapDispatchToProps = (dispatch) => ({
login(accountElement,passwordElement) {
console.log(accountElement, passwordElement);
会打印出那两个组件
console.log(accountElement.value, passwordElement.value);
两个组件的值
}
})
打印出来的结果如下
用户名和密码校验
需要把拿到的用户名和密码发送给后端,看匹不匹配
const mapDispatchToProps = (dispatch) => ({
login(accountElement, passwordElement) {
dispatch(actionCreator.login(accountElement.value, passwordElement.value))
}
})
src/pages/login/store/actionCreator.js
这种网络请求是我的盲点
import axios from "axios";
export const login = (account, password) => {
return (dispatch) => {
axios.get("/api/login.json?account=" + account + "&password=" + password).then((res) => {
console.log(res);
})
}
}
public/api/login.json
这个数据就是说任何人都能登录
{
"success":true,
"data":true
}
登陆成功后两件事:显示“退出登录”+跳转至首页
- 显示“退出登录
src/pages/login/store/actionCreator.js
export const login = (account, password) => {
return (dispatch) => {
axios.get("/api/login.json?account=" + account + "&password=" + password).then((res) => {
const result = res.data.data;
if (result) {
//如果登陆成功,要派发action修改login的数据
dispatch(changeLogin())
} else {
alert("登录失败")
}
})
}
}
src/pages/login/store/reducer.js
import { fromJS } from "immutable";// 导入immutable模块中fromJS方法
//使用fromJS将其变为immutable对象数据(只能使用set、get)
import * as actionType from "./actionType";
const defaultState = fromJS({
login:false
})
export default (state = defaultState, action) => {
switch (action.type) {
case actionType.CHANGE_LOGIN:
return state.set("login", action.value);
default:
return state;
}
}
;
实现登录成功后修改状态
- 跳转至首页
login/index.js中获取login数据,如果当前login数据为true,就跳转到首页,否则就渲染“用户名”和“密码”输入页面
注意:因为都在props里面,函数与变量不能够重名
。。。
import { Redirect } from "react-router-dom"; !!!!!!!注意这里的新组件
class Login extends PureComponent {
render() {
const { loginStatus } = this.props;
if (!loginStatus) {//没登陆,渲染当前页面
return (
<LoginWrapper>
<LoginBox>
<Input placeholder="账号" ref={(input) => { this.account = input }}></Input>
<Input placeholder="密码" type="password" ref={(input) => { this.password = input }}></Input>
<Button onClick={() => this.props.login(this.account, this.password)}>登录</Button>
</LoginBox>
</LoginWrapper>
)
} else { //重定向到首页
return <Redirect to="/" /> !!!!!! <Redirect to="/" /> 的应用
}
}
}
const mapStateToProps = (state) => ({
loginStatus: state.getIn(["login", "login"])
})
const mapDispatchToProps = (dispatch) => ({
login(accountElement, passwordElement) {
dispatch(actionCreator.login(accountElement.value, passwordElement.value))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Login);
盲点:
import { Redirect } from "react-router-dom";
新组件
修改header组件,点击"退出登录",修改login值
行为触发是在header/index.js
但数据修改是在login/store中
因此在header/index.js中,必须要引入login/store/actionCreator.js
import { actionCreator } from "./store";
import { actionCreator as loginActionCreator } from "../../pages/login/store";
//上面这句是用来修改login登录状态的,当前文件夹下的 actionCreator无法修改login
{
login ? <Navitem onClick={this.props.logout} className="right">退出登录</Navitem>:<Link to="/login"><Navitem className="right">登录</Navitem></Link>
}
const mapStateToProps = (state) => {
return {
login:state.getIn(["login","login"])
}
}
const mapDispatchToProps = (dispatch) => {
return {
logout() {
dispatch(loginActionCreator.logout());
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Header);
export const logout = () => ({
type: actionType.LOGOUT,
value:false
})
export default (state = defaultState, action) => {
switch (action.type) {
case actionType.LOGOUT:
return state.set("login", action.value);
default:
return state;
}
};