09月10, 2016

React系列之-使用React+Redux中遇到的坑

初次相遇总是美好的,相识久了总是会遇到很多问题。

随着开发的不断深入,也逐渐遇到了很多问题,并预计还在不断更新中,因为项目还未完成。

路由

  • onEnter中的callback(), 当获取判断状态是异步操作时,特别有用。react-router文档中这么写到:

    onEnter(nextState, replaceState, callback?)
    当 route 即将进入时调用。它提供了下一个路由的 state,一个函数重定向到另一个路径。this 会触发钩子去创建 route 实例。
    当 callback 作为函数的第三个参数传入时,这个钩子将是异步执行的,并且跳转会阻塞直到 callback 被调用。
    
  • onEnter往往用来做权限验证,登录验证

  • 需要注意的是,dispatch是异步的,等待获取结果需要在之后的then()里使用

redux中的state和react内部的state

  • 这两者之间没什么关系。各干各的事。
  • redux中的state实际上也就是通过reducer处理之后挂在store树上一个状态。
  • 通过redux的connect()方法可以将这个state值变成组件的props,供组件使用。

reducer返回的state

  • 一个reducer文件中可能会有多个子reducer,每个一个子reducer中的state参数对应自己那部分的state数据,不是全局state本身。
  • Redux提供了combineReducers()来管理各个子reducer
  • 不能修改state, 需要返回一个新的state。这样便于做到“回退/撤销”,追踪全局状态。 另外在react的components里往往还需要通过shouldComponentUpdate(nextProps, nextState)函数来进行性能优化
  • 并且需要有default的处理,即遇到未知actioin时,一定要返回旧的state

关于reducer的划分

依据对state对象的设计。可以理解为数据库中的一张表;关于层级保持多深,还没有很好的实践

多个异步的action creator

  • 在进行某些操作的时候,我们可能需要触发好几个action来完成这个操作。同时呢这些action或者有先后依赖顺序,或许需要一起完成才可能拿到最终的值。这时我们就需要用promise来帮助我们。
  • 在redux中我们可以用redux-thunk中间件来构建异步action。(还可以dispatch函数或者Promise, 比如从异步接口取到数据)
  • 对于同步的action我们可以使用Promise.resolve()来包装下。
  • 需要记得每一层都要return, 否则最外层被调用之后是undefined的
return (dispatch, getStore) => {
    return api.login(data).then(res => {
        if(res.code == 1){
            return Promise.resolve( dispatch(loginSuccess(res.data)) )
                            .then( () => {
                                return true
                            })
        }else if(res.code == -1){
            return Promise.resolve( dispatch(loginError(res.message)) )
                            .then( () => {
                                return Promise.resolve(
                                    dispatch(showDialog('登录失败')).then( () => {
                                    return false
                                })    
                            })
        }
    })
}

redux-form

  • 组件更新很多,但是小问题也很多。
  • 建议是,如果表单中的标准控件很多,适合使用。
  • 但如果控件个数不多,但是里面自定义的控件又居多,那么建议还是不用。因为可能需要单独处理自定义控件的状态,反而增加了工作量。

  • 设置初始值,enableReinitialize: true,initialValues是一个对象,它的key值与组件里的"name"对应;

  • SubmissionError触发后,store树上form的submitFailed变成true, 且目前找不到重新设置为false的方法
  • reset, 不能自动重置自定义组件的值,可能需要手动重置(一般通过内部state的方法来解决);
  • sync error + field array, field 被移除但是values里保存的依然是initvalue,没有改变。原因是渲染field array的值是从store树上拿的,改为initialValues初始化后解决。

直接使用了数组的引用, 改变了原数组

在组件内部使用了一个变量,这个变量指向了store树上的一个状态,在没有使用immutable的前提下,改变这个变量,实际上也把store树上的状态改变了。这种情况是一个双刃剑,有利有弊。使用时要比较明确可能会发生的后果。

无状态component

  • 一般的组件有有完整的生命周期。无状态组件,则更像是一个函数返回一段html片段,只有render方法。
  • 它没有实例化的过程,不需要被分配多余的内存,可以提高整体渲染性能。
  • 它只涉及到props,而不涉及到state的操作。
const HelloComponent = (props) => {
  return <div>Hello {props.name}</div>
}

axios的Content-Type

  • 默认是'application/json'
  • 这种情况下PHP无法直接从 $_POST 对象从上面的请求中获得内容。
  • 解决办法:
  • 设置axiosContent-Type:application/x-www-form-urlencode, querystring转换要传参数的格式。
  • php从php://input里获得原始输入流, 再json_decode成对象。具体见四种常见的 POST 提交数据方式

参考

Redux中文文档 深入到源码:解读 redux 的设计思路与用法

本文链接:https://imjiaolong.cn/post/react-summary.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。