手把手教你redux/react-redux使用

302 阅读6分钟

创建项目:

通过react-app脚手架创建一个名为study-redux工程

npm init react-app study-redux

当你看到下图时表示项目创建成功

按照上图中的指示,通过命令行运行工程:

cd study-redux
yarn start

工程运行起来后大概是下图的样子

安装redux/react-redux

在工程根目录指定下面的命令,安装redux react-redux依赖

npm install redux react-redux

在package.json文件中看到react-redux/redux表示安装成功,具体如下图:这里我使用的redux版本是4.0.5

依赖安装完毕,开始使用redux管理你的数据

改造App.js并且创建Home组件

首先改造你的工程代码,找到src/App.js;当前App.js代码如下:

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;


删除部分无用代码,App.js代码如下

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
	return <div className="App"></div>;
}

export default App;

在src文件夹下创建Pages文件夹,并在Pages文件夹下创建Home.js;具体结果下图

将Home组件引入到App.js,显示Home组件,此时App.js代码如下:

import React from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Pages/Home';

function App() {
	return (
		<div className="App">
			<Home />
		</div>
	);
}

export default App;

当前实图大概是下图的模样

创建redux的store

创建store需要通过redux中createStore方法,具体代码如下


import React from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Pages/Home';
import { createStore } from 'redux';

const initState = {
	init: '我是一个测试数据',
};
const reducers = (state = initState, action) => {
	switch (action.type) {
		case 'value':
			return state;

		default:
			return state;
	}
};

const store = createStore(reducers);
function App() {
	return (
		<div className="App">
			<Home />
		</div>
	);
}

export default App;

其中reducer是一个简单的函数,这里先使用一个比较容易看懂的函数作为入门教程,开发过程中会将reducer单独提出去 这里已经创建的store数据,怎么将store的数据绑定到react组件中呢?这里就用到了react-redux;

将store绑定到组件

这个简单,在App.js中通过import将react-redux中的Provider引入;具体代码如下

import React from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Pages/Home';
import { createStore } from 'redux';
//新增Provider
import { Provider } from 'react-redux';
const initState = {
	init: '我是一个测试数据',
};
const reducers = (state = initState, action) => {
	switch (action.type) {
		case 'value':
			return state;

		default:
			return state;
	}
};

const store = createStore(reducers);
function App() {
	return (
	//将store挂载到store上
		<Provider store={store}>
			<div className="App">
				<Home />
			</div>
		</Provider>
	);
}

export default App;

已经将数据挂载到组件,怎么才能获取到这个组件呢?在src/Pages/Home.js中引入react-redux的connect具体看下面的代码:


import React, { Component } from 'react';
//引入connect
import { connect } from 'react-redux';

const Home = (props) => {
	const { init } = props;
	return (
		<div>
			<h2>我是Home组件</h2>
			<h3>我等待接受HomeRedux中的数据</h3>
			<h4>我是redux数据:{init}</h4>
		</div>
	);
};
//使用mapStateToProps将store数据绑定到当前Home组件
const mapStateToProps = (state, ownProps) => {
	return {
	    //需要绑定的数据名,这里的名字要与reducer中的名字一致
		init: state.init,
	};
};
export default connect(mapStateToProps)(Home);

这是页面的运行结果如下图:

刚刚在App.js中的数据【我是一个测试数据】已经显示在Home组件中了。

当然,如果你想在其他页面显示【我是一个测试数据】这段数据也可以这么写,比如在src/Pages文件夹创建About.js组件;这是工程的目录及About代码如下:

同样将About通过react-redux的connect方法将数据绑定到About组件;About.js代码如下


import React, { Component } from 'react';
import { connect } from 'react-redux';
class About extends Component {
	render() {
	    // 类组件,通过this.props获取connect绑定到props上的数据
		const { init } = this.props;
		return (
			<div>
				<h2>我是About组件</h2>
				<h4>我要现实reducer数据:{init}</h4>
			</div>
		);
	}
}
const mapStateToProps = (state, ownProps) => {
	return {
		init: state.init,
	};
};
export default connect(mapStateToProps)(About);

如果你需要多条数据,可以在reducer中添加数据,比如在app.js中添加about;具体代码如下:


import React from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Pages/Home';
import About from './Pages/About';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const initState = {
	init: '我是一个测试数据',
	about: '我是about的数据',
};
const reducers = (state = initState, action) => {
	switch (action.type) {
		case 'value':
			return state;

		default:
			return state;
	}
};

const store = createStore(reducers);
function App() {
	return (
		<Provider store={store}>
			<div className="App">
				<Home />
				<About />
			</div>
		</Provider>
	);
}

export default App;

同时如果想取这里的数据你可以这样:在about.js中:


import React, { Component } from 'react';
import { connect } from 'react-redux';
class About extends Component {
	render() {
		const { init, about } = this.props;
		return (
			<div>
				<h2>我是About组件</h2>
				<h4>我要现实reducer数据:{init}</h4>
				<h4>我是about数据:{about}</h4>
			</div>
		);
	}
}
const mapStateToProps = (state, ownProps) => {
	return {
		init: state.init,
		about: state.about,
	};
};
export default connect(mapStateToProps)(About);

通过以上的一些代码可以看到,我现在已经将redux数据绑定到组件上,但是将数据放在app.js中确实不太雅观,而且home组件数据与About组件数据耦合在一起,数据少的时候没问题,数据量达到话不便维护;所以,我准备把reducer的数据拆分出去。

拆分数据

在src文件夹下创建redux文件,在redux文件夹中创建reducer文件夹,在reducer文件夹中创建index.js/HomeReduser.js/AboutReducer.js;此时工程目录为下图

在reducer/index.js输入一下代码:

//引入combineReducers,合并reducer
import { combineReducers } from 'redux';
import HomeReducer from './HomeReducer';
import AboutReducer from './AboutReducer';
export default combineReducers({
	HomeReducer,
	AboutReducer,
});

在reducer/HomeReducer.js输入一下代码


export const CHANGE_INIT = 'CHANGE_INIT';
//声明初始数据
const initState = {
	init: 'home初始数据',
	array: [1, 2, 3],
};
//文件返回一个纯函数
export default (state = initState, action) => {
	switch (action.type) {
		case CHANGE_INIT:
			return Object.assign({}, state, {
				init: action.init,
			});

		default:
			return state;
	}
};

通过这种书写方式将怎么将reducer文件夹数据与App.js文件中的reducer联系起来呢? 下面我门改写一下App.js代码: 找到App.js,改写代码如下,具体看注释


import React from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Pages/Home';
import About from './Pages/About';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
//将刚刚写的redux/reducer/index引入到App.js
import reducers from './redux/reducer/index';
//注释之前reducer代码,
// const initState = {
// 	init: '我是一个测试数据',
// 	about: '我是about的数据',
// };
// const reducers = (state = initState, action) => {
// 	switch (action.type) {
// 		case 'value':
// 			return state;

// 		default:
// 			return state;
// 	}
// };

const store = createStore(reducers);
function App() {
	return (
		<Provider store={store}>
			<div className="App">
				<Home />
				<About />
			</div>
		</Provider>
	);
}

export default App;

你看懂了吗?
没看懂????
出门右转~不送了

既然我使用了combineReducers合并reducer,有替换App.js中的reducer路径,会不会影响我在组件中获取redux数据的方式,这是个好问题。来,接着看此时组件如何获取redux中reducer数据;
找到src/Pages/Home.js;修改代码如下:


import React, { Component } from 'react';
import { connect } from 'react-redux';

const Home = (props) => {
	const { init } = props;
	return (
		<div>
			<h2>我是Home组件</h2>
			<h3>我等待接受HomeRedux中的数据</h3>
			<h4>我是redux数据:{init}</h4>
		</div>
	);
};
const mapStateToProps = (state) => {
    // 【3】
    console.log(state)
	return {
    //注释
    //init: state.init,

    //新增,注意此处的HomeReducer使用的是redux/reducer/index.js中combineReducers变量名,如有疑问,最好在标记【3】中打印一下state,自能明白
		init: state.HomeReducer.init,
	};
};
export default connect(mapStateToProps)(Home);


此时观察页面,你将看到如下视图,这样你就可以在组件中获取到redux/reducer/HomeReducer.js中的数据了

现在,我将redux数据绑定到组件,并且拆分了reducer数据;下面解决另一个问题,如何修改redux数据呢?

下一节更新

说明

第一篇教程,能力有限欢迎指导