1. 程式人生 > >自己實現React-Redux

自己實現React-Redux

React-Redux核心

React-Redux核心API:

Redux 官方提供的 React 繫結庫。具有高效且靈活的特性。

  • Provider 元件
    用於在應用頂層提供store。
  • connect 函式
    用於給元件提供store的狀態和dispatch方法。接收四個引數,返回一個高階元件。

逐步程式碼實現(涉及ES6和JSX語法):

Provider

1、首先Provider是一個頂層容器元件,接收一個store引數:

	import React from 'react';
	import PropTypes from 'prop-types';
	
	export default class Provider extends React.Component {
		static propTypes = {
			store: PropTypes.object.isRequired
		}
		render(){
			return this.props.children;
		}
	}

2、將store掛載到context上,以便讓子元件訪問到:

	import React from 'react';
	import PropTypes from 'prop-types';
	
	export default class Provider extends React.Component {
		static propTypes = {
			store: PropTypes.object.isRequired
		}
		/* 新增程式碼 */
		getChildrenContext(){
			return { store: this.props.store};
		}
		* *********** */
		render(){
			return this.props.children;
		}
	}

可以看到,Provider的實現非常簡單。

connect

connect的實現比較複雜,它應接收四個引數:

  • mapStateToProps 回撥函式,接收當前的state作為引數,返回一個物件作為元件的引數;
  • mapDispatchToProps 回撥函式,接收store的dispatch方法作為引數,返回值同上;
  • mergeProps 回撥函式,接收前兩個函式的返回值以及元件本身的引數作為引數,返回值作為傳遞給元件的最終的引數。
  • options 配置項,暫且不管。

1、connect大概的樣子:
它接收三個引數,返回一個高階元件。

	import React from 'react';
	import PropTypes from 'prop-types';
	
	const connect = (
		mapStateToProps,
		mapDispatchToProps,
		mergeProps
	) => {
		const withConnect = Comp => 
			class CompWithConnect extends React.Component{
				render(){
					const finalProps = this.props;
					
					return <Comp { ...finalProps } />
				}
			};
		return withConnect;
	};
	export default connect;

2、先讓元件獲取store,並獲取所需的state及dispatch方法:

	import React from 'react';
	import PropTypes from 'prop-types';
	
	const connect = (
		mapStateToProps,
		mapDispatchToProps,
		mergeProps
	) => {
		const withConnect = Comp => 
			class CompWithConnect extends React.Component{
				/* 新增程式碼 */
				static contextTypes = {
					store: PropTypes.object
				}
				/* ********** */
				render(){
					/* 新增程式碼 */
					const currentState = this.context.store.getState();
					const dispatch = this.context.store.diaptch;
					/* ********** */
					const finalProps = this.props;
					
					return <Comp { ...finalProps } />
				}
			};
		return withConnect;
	};
	export default connect;

3、考慮到引數是可選的,應提供三個方法的預設值:

	import React from 'react';
	import PropTypes from 'prop-types';
	
	/* 新增程式碼 */
	const defaultMapStateToProps = () => ({});
	const defaultMapDispatchToProps = () => ({});
	const defaultMergeProps = (
		mappedStateProps, 
		mappedDipatchProps, 
		ownProps
	) => ({
		...ownProps,
		...mappedStateProps,
		...mappedDipatchProps
	});
	/* ********** */
	
	const connect = (
		mapStateToProps,
		mapDispatchToProps,
		mergeProps
	) => {
		/* 新增程式碼 */
		const finalMapStateToProps = mapStateToProps||defaultMapStateToProps;
		const finalMapDispatchToProps = mapDispatchToProps||defaultMapDispatchToProps;
		const finalMergeProps = mergeProps||defaultMergeProps;
		/* ********** */

		const withConnect = Comp => 
			class CompWithConnect extends React.Component{
				
				static contextTypes = {
					store: PropTypes.object
				}
				
				render(){
					const currentState = this.context.store.getState();
					const dispatch = this.context.store.diaptch;
					const finalProps = this.props;
					
					return <Comp { ...finalProps } />
				}
			};
		return withConnect;
	};
	export default connect;

4、計運算元元件的引數:

	import React from 'react';
	import PropTypes from 'prop-types';
	
	const defaultMapStateToProps = () => ({});
	const defaultMapDispatchToProps = () => ({});
	const defaultMergeProps = (
		mappedStateProps, 
		mappedDipatchProps, 
		ownProps
	) => ({
		...ownProps,
		...mappedStateProps,
		...mappedDipatchProps
	});
	
	const connect = (
		mapStateToProps,
		mapDispatchToProps,
		mergeProps
	) => {
		const finalMapStateToProps = mapStateToProps||defaultMapStateToProps;
		const finalMapDispatchToProps = mapDispatchToProps||defaultMapDispatchToProps;
		const finalMergeProps = mergeProps||defaultMergeProps;
		/* 新增程式碼 */
		const computedProps = (currentState, dispatch, ownProps) => finalMergeProps(finalMapStateToProps(currentState), finalMapDispatchToProps(dispatch), ownProps);
		/* ********** */
		const withConnect = Comp => 
			class CompWithConnect extends React.Component{
				
				static contextTypes = {
					store: PropTypes.object
				}
				render(){
					const currentState = this.context.store.getState();
					const dispatch = this.context.store.diaptch;
					/* 修改程式碼 */
					const finalProps = computedProps(currentState, dispatch, this.props);
					/* ********** */
					return <Comp { ...finalProps } />
				}
			};
		return withConnect;
	};
	export default connect;