Skip to main content

Redux

Disclaimer: It is recommended to use npm install @reduxjs/toolkit, please see the documentation for details.

Installation

npm install redux

Browser installation Redux DevTools

Install Thunk

npm install --save redux-thunk

App.js configuration, Provider

import React, { Component } from "react";
import Header from "./common/header/index";
import { Provider } from "react-redux";
import store from "./store";
import Login from './pages/login';
import Write from './pages/Write/index'
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/home";
import Detail from "./pages/detail";

class App extends Component {
render() {
return (
<Provider store={store}>
<BrowserRouter>
<Header />
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" exact element={< Login />} />
<Route path="/write" exact element={< Write />} />
<Route path="/detail/:id" exact element={<Detail />} />
</Routes>
</BrowserRouter>
</Provider>
);
}
}

export default App;

example

create store file

store file in the root directory

Create index.js and reducer.js

index.js

import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducer from "./reducer";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));

export default store;

reducer.js

import { combineReducers } from "redux-immutable";
import { reducer as headerReducer } from "../common/header/store";
import { reducer as homeReducer } from "../pages/home/store";
import { reducer as detailReducer } from '../pages/detail/store/'
import { reducer as loginReducer } from '../pages/login/store'

const reducer = combineReducers({
header: headerReducer,
home: homeReducer,
detail:detailReducer,
login:loginReducer,
});

export default reducer;

Secondary store files

Create index.js and reducer.js and actionTypes.js and actionCreators.js

index.js

import reducer from "./reducer";
import * as actionCreators from './actionCreators'
import * as actionType from './actionType'

export { reducer,actionCreators,actionType };

reducer.js

import { fromJS } from "immutable";
import * as actionType from './actionType'

const defaultState = fromJS({
topicList: [],
ListItem:[],
recommimg:[],
ListPage:1,
scrollGoBack:false
});

const calculate = (state = defaultState, action) => {
switch (action.type) {
case actionType.CHANGE_HOME_DATA:
return state.merge({
topicList:fromJS(action.topicList),
ListItem:fromJS(action.ListItem),
recommimg:fromJS(action.recommimg)
});
case actionType.ADD_ARTICLE_LIST:
return state.merge({
ListItem:state.get('ListItem').concat(action.list),
ListPage:action.nextPage
});
case actionType.GET_BACK_TOP:
return state.set('scrollGoBack',action.show)
default:
return state;
}
};

export default calculate;

actionTypes.js

export const CHANGE_INPUT = 'changeInput/CHANGE_INPUT'
export const ADD_ITEM = 'addItem/ADD_ITEM'
export const DELETE_ITEM = 'deleteItem/DELETE_ITEM'
export const GET_DETAIL_DATA = 'header/GET_DETAIL_DATA';

actionCreators.js

import axios from "axios";
import * as actionType from './actionType'
import { fromJS } from 'immutable';

export const changeInputAction = (value) => ({
type: actionType.CHANGE_INPUT,
value
})

export const addItemAction = () => ({
type: actionType.ADD_ITEM
})

export const deleteItemAction = (index) => ({
type: actionType.DELETE_ITEM,
index
})

export const getHomeInfo = () => {
return (dispatch) => {
axios.get('/api/home.json').then((res)=>{
const result = res.data.data;
dispatch(changeHomeDate(result))
})
}
};

const changeHomeDate = (result) => ({
type:actionType.CHANGE_HOME_DATA,
topicList:result.topicList,
ListItem:result.ListItem,
recommimg:result.recommimg
});

export const getmorelist =(page)=>{
return (dispatch) =>{
axios.get('/api/get.json?page=' + page).then((res)=>{
const result = res.data.data;
/* console.log(result); */
dispatch(addHomeList(result,page + 1));

})
}
};

const addHomeList = (list,nextPage) => ({
type:actionType.ADD_ARTICLE_LIST,
list:fromJS(list), /* Only list, if you want to concat */
nextPage
})

export const getBackTop = (show) => ({
type:actionType.GET_BACK_TOP,
show
})

front-end connect

import React, { PureComponent } from "react";
import Topic from "./components/Topic";
import Writer from "./components/Writer";
import Recommend from "./components/Recommend";
import List from "./components/List";
import { HomeWrapper, HomeLeft, HomeRight,BackTop } from "./style";
import { connect } from 'react-redux';
import { actionCreators } from './store';


class Home extends PureComponent {

componentDidMount(){
this.props.changeHomeDate();
this.bindEvent();
};

bindEvent(){
window.addEventListener('scroll',this.props.getBack);
}

handleBackTop(){
window.scrollTo(0,0);
}

render() {
const {showScroll} = this.props;
return (
<HomeWrapper>
<HomeLeft>
<img
className="change_img"
src="https://i.ytimg.com/vi/z7_9XW_IUYM/maxresdefault.jpg"
alt=""
/>
<Topic />
<List />
</HomeLeft>
<HomeRight>
<Recommend />
<Writer />

</HomeRight>
{showScroll? <BackTop onClick={this.handleBackTop}><h3>顶部</h3></BackTop> : null}

</HomeWrapper>
);
}
};

const mapState = (state) => ({
showScroll:state.getIn(['home','scrollGoBack'])
})

const mapDispatch = (dispatch) => ({
changeHomeDate(){
dispatch(actionCreators.getHomeInfo())
},
getBack(){
if(document.documentElement.scrollTop > 200){
dispatch(actionCreators.getBackTop(true));
}else{
dispatch(actionCreators.getBackTop(false));
}
}
});

export default connect(mapState,mapDispatch)(Home);