首页
学习
活动
专区
圈层
工具
发布

现代Web开发系列教程_04

本篇使用redux结合react重写刚才那个很简单的hello world示例。

redux的理念

redux有三个重要的理念:单一数据源、状态是只读的、使用纯函数转换状态。具体见链接

安装redux与react-redux

1

npm install redux react-redux --save

状态转换纯函数

web-src/js/components/GreetingConstant.js

1

export const CHANGE_NAME = 'CHANGE_NAME';

web-src/js/reducers/GreetingReducer.js

代码语言:javascript
复制
import {CHANGE_NAME} from '../constants/GreetingConstant.js'

const initialState = {
  name: '',
  output: ''
}

export function GreetingReducer(state = initialState, action) {

    if (typeof state === 'undefined') {
        return initialState;
    }

    switch(action.type) {
        case CHANGE_NAME:
            return Object.assign({}, state, {
                name : action.name,
                output: 'Hello, ' + action.name
            });
        default:
            return state;
    }
};

这两个文件很简单,GreetingConstant.js里定义了action类型的常量,GreetingReducer.js就是一个普通纯函数,它的工作就是根据action转换state。

actionCreator

action是一个纯对象,其中保存了用来转换state的信息,一般包括type类型及其它参数,官方是这样定义的Actions are payloads of information that send data from your application to your store.

actionCreator则是产生action的方法。

web-src/js/actions/GreetingAction.js

代码语言:javascript
复制
import { CHANGE_NAME } from '../constants/GreetingConstant.js'

export function changeName(name) {
    return {
        type : CHANGE_NAME,
        name: name
    };
}

组件

在redux与react项目中,组件分为Presentational ComponentsContainer Components,有的地方叫Dump ComponentsSmart Components

Presentational Components

Container Components

Purpose

How things look (markup, styles)

How things work (data fetching, state updates)

Aware of Redux

No

Yes

To read data

Read data from props

Subscribe to Redux state

To change data

Invoke callbacks from props

Dispatch Redux actions

Are written

By hand

Usually generated by React Redux

简单来说Presentational Components是完全根据props属性决定行为与展现的组件,完成不感知redux的存在。Container Component则负责从state中抽取属性,分发redux's action,这里一般会用到reduxconnect方法,还是看下面的代码。

web-src/js/components/GreetingComponent.js,这个就是一个Presentational Components组件

代码语言:javascript
复制
import React from 'react'

const noop = function(){};

class GreetingComponent extends React.Component{

    constructor(props){
        super(props);
        this._changeName = this.changeName.bind(this);
    }

    changeName(e){
        this.props.changeName(e.target.value);
    }

    render() {
        return (
            <div>
                <input value={this.props.name} onChange={this._changeName}/><br/>
                <label>{this.props.output}</label>
            </div>
        );
    }
};

GreetingComponent.propTypes = {
    changeName: React.PropTypes.func.isRequired,
    name: React.PropTypes.string.isRequired,
    output: React.PropTypes.string.isRequired
};

GreetingComponent.defaultProps = {
    changeName: noop,
    name: '',
    output: ''
};

export default GreetingComponent;

web-src/js/containers/GreetingContainer.js,这个就是一个Container Component组件

代码语言:javascript
复制
import { connect } from 'react-redux'

import GreetingComponent from '../components/GreetingComponent.js'

import {changeName} from '../actions/GreetingAction.js'

const mapStateToProps = (state) => {
  return {
    name: state.name,
    output: state.output
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    changeName: (name) => {
      dispatch(changeName(name))
    }
  }
}

const GreetingContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(GreetingComponent)

export default GreetingContainer

web-src/js/components/GreetingApp.js,这个就是一个Presentational Components组件

代码语言:javascript
复制
import React from 'react'

import GreetingContainer from '../containers/GreetingContainer.js'

export default class GreetingApp extends React.Component{
    render(){
        return <GreetingContainer/>
    }
}

使用Provider将state与组件关联起来

web-src/js/entries/demo3.js

代码语言:javascript
复制
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import {GreetingReducer} from '../reducers/GreetingReducer.js'
import GreetingApp from '../components/GreetingApp.js'

let store = createStore(GreetingReducer)

render(
  <Provider store={store}>
    <GreetingApp />
  </Provider>,
  document.getElementById('reactHolder')
)

这里用到了reduxProvider,它会把store附属到组件树的context上,其子组件就都可以访问到store了。

本篇源代码地址

下一篇
举报
领券