JavaScript学习笔记

当下对React.js的再思考

2019-11-27  本文已影响0人  钢笔先生

Time: 2019-11-27

之前在比赛中写前端工程时,使用了如下几个关键的技术点:

首先从redux讲起。

redux的设计原则是用单个字典来存储应用的状态树store,通过action来传递修改状态的信息包,具体的修改是通过定义的reducers函数来执行。

也即我们需要将actions --> reducers --> store三者串联起来。

这三者是为了搭建起来一个自动响应的框架,搭建完是不动的,需要外界dispatch某个action来触发,相当于现在定义了一个状态机,外界的输入进来才会触发响应。

store会在应用的index.js中绑定到全局。

import { store } from './_store'

const rootElement = document.getElementById("root")

console.log("store状态:", store.getState()) // 可以拿到状态

// store已经绑定到了整个App
ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, rootElement
)

一般我们会定义一个store.js用于表示状态,我们会

关于组件,我们抽象为两层组件:

容器组件负责将状态和要触发的动作绑定到展示组件,展示组件只需要关注自己如何通过HTML + CSS元素表达想要展示的内容,容器组件会把要用到的数据和要dispatch的动作注入到展示组件的props

举个例子:

import { Blacklist } from '../../_pages/company'
import { connect } from 'react-redux'
import { listBlacklistAsync } from '../../_actions/company.actions'

// 容器负责注入状态显示和行为定义,作为显示组件的props

// store状态映射到组件
// store已经在index.js中绑定到应用,这里直接取用即可
// blacklist是用于props的键
const mapStateToProps = state => ({
    blacklist: state.company.blacklist,
    fetchStatus: state.company.fetchStatus,
})

// 注入到展示组件的props中的回调方法
const mapDispatchToProps = dispatch => ({
    listBlacklistAsync: () => dispatch(listBlacklistAsync())
})

// 连接到展示组件
export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Blacklist)

容器组件和展示组件通过connect方法绑定到一起。背后store状态机已经搭建好了。

展示组件调用容器组件准备好的属性和方法:

componentDidMount() {
        this.props.listBlacklistAsync() // 先分发查询修改状态树
    }


render() {
        // this.createData(`0xc83b2cf766d3165acc2fc9164641380088defd1b`, "xx于xx年xx月xx日未还款金额xx元"),
        let rows = []
        // 需要根据状态判定是否已经结束获取
        console.log("组件内显示黑名单:", this.props.blacklist)

        if (this.props.blacklist !== undefined) {
            // this.props.blacklist.map((item, i) => {
            //     rows.push(this.createData(item.weid, item.record))
            // })
            rows = this.props.blacklist
        }

        const { classes } = this.props

        if (this.props.fetchStatus === FETCH_STATUS.FETCH_BEGIN) {
            return (
                <div align="center">
                    <br />
                    <CircularProgress />
                </div>
            )
        }
....

关于action的定义:

程序需要调用的外部数据,我们用fetch获取,获取到的数据可以用到action定义中,外部数据的获取是为了修改组件的状态,而组件的状态现在是由store接管。

看一个action定义的例子:


// dispatch action
const listLoanRequestRecords = (json) => {
    return {
        type: types.LOAN_REQUEST_RECORDS,
        payload: json.data
    }
}


// 定义行为,行为会在容器组件中设定给props,具体显示组件中择时触发
const listLoanRequestRecordsAsync = () => {
    return dispatch => {
        dispatch(fetchBegin())
        // 通过服务拿到数据,最后作为action的payload,action的payload用于修改store,修改行为由reducer执行
        companyServices.listLoanRequestRecords("WeBank").then(
            json => {
                if (json.status === 200) {
                    dispatch(fetchSuccess())
                }
                dispatch(listLoanRequestRecords(json))
            }
        )
    }
}

action是在reducers中使用。所以我们看下reducers的定义:

// 获取用户请求列表
export function loanRequestRecordsReducer(state = [], action) {
    switch (action.type) {
        case types.LOAN_REQUEST_RECORDS:
            return [
                ...state,
                ...action.payload
            ]
        default:
            return state
    }
}

reducer是纯函数,接收当前状态的值然后根据action带来的动作类型和数据包修改store。

不要看参数state=[]就认为store是空,这是默认参数,拿到的是当前的数据。

另外,reducer指定的键名就是store字典树的键名。

比如在store中:

// 会根据定义的键值生成对应的以第一层键指定的store
const rootReducer = combineReducers({
    company: companyReducer,
    government: governmentReducer,
    user: userReducer,
    common: commonReducer
})

一级键就是这四个值:company, government, user, common

这个之前写过一个笔记:
在combineReducers用的是对象,按照key来标记对应的是哪个reducer,键是state的属性名!

这太重要了,我太喜欢这个了,解决了我的困惑。

下一个困惑是,state给空,每次调用都是在干嘛?

是根据分离的reducer对应的属性直接抽出来一段数据过来当参数吗?

如果修改的话就在容器组件中dispatch修改方法

如果只是读取,就在容器组件中getState传到值属性里。

Q: fetch返回的Promise如何触发状态更新?

A: fetch(url).then(response => response.json()).then(json => console.log(json))

这样就串起来应用状态和数据读取的全貌了。

有点乱,后续有时间再梳理。

上一篇 下一篇

猜你喜欢

热点阅读