【问题标题】:Redux store goes undefined despite successful initialization尽管初始化成功,Redux 存储仍未定义
【发布时间】:2015-12-30 18:43:02
【问题描述】:

我有一个控制器组件“VideoManager”,它呈现一个视图组件“视频”。如果可以通过 props 获得本地视频流,则视图组件会渲染一个本地视频流,否则它会渲染一个通过 getUserMedia 初始化视频流的按钮(我已将 getUserMedia API 调用包装在一个 Promise 中。查看控制台日志,我看到状态被正确初始化为空的不可变映射。但是,当我单击按钮时,在承诺完成之前状态似乎变为“未定义”,因此引发错误“无法读取未定义的属性 'getIn'”。大概这是因为在承诺完成之前状态会短暂改变(尽管我不确定为什么它会进入未定义状态而不是保持在初始状态)。

这是我的控制器组件:

import React from 'react';
import {connect} from 'react-redux';
import Video from './Video';
import bowser from 'bowser';
import * as actionCreators from '../action_creators';

export const VideoManager = React.createClass({
  render: function() {
    return <div>
      <div>This is the VideoManager component.</div>
      <div>{bowser.chrome && bowser.version > 34 ? "Welcome!" : "Sorry, we only support Chrome version 34 and above"}</div>
      <Video {...this.props}/>
    </div>
  }
});

function mapStateToProps(state) {
  return{
    localStreamURL: state.getIn(['localStreamInfo', 'localStreamURL'])
  };
}

export const VideoManagerContainer = connect(mapStateToProps, actionCreators)(VideoManager);

这是我的视图组件:

import React from 'react';

export default React.createClass({

  render: function() {
    const videoAndAudio = {audio: false, video: true};
    return <div>
      <div>This is the Video component.</div>
      {this.props.localStreamURL ? <video id="localVideo" src={this.props.localStreamURL}></video> : <button onClick={() => this.props.getLocalVideo(videoAndAudio)}>Get Local Video</button>}
    </div>
  }
});

我的动作创建者:

export function getLocalVideo(config) {
  return {
    type: 'GET_LOCAL_VIDEO',
    config
  };
}

还有我的减速机:

import {List, Map} from 'immutable';
import {createLocalStream} from './utils/webrtc_utils';

function getLocalVideo(state, config){
    createLocalStream(config).then(
    function(stream){    
        return state.set('localStreamInfo', Map({
            localStream: stream,
            localStreamURL: URL.createObjectURL(stream)
        }));
 }, function(err){
        console.log("Stream collection failed: ", err);
 });
}

export default function(state = Map(), action){
    switch(action.type) {
        case 'GET_LOCAL_VIDEO':
            return getLocalVideo(state, action.config);
    }
    return state;
}

我的假设是否正确,即承诺是出轨的地方?如果是这样,我如何防止“连接”在承诺完成之前告诉控制器有一个新状态?

编辑
为了后代,这里是我承诺包装的 getUserMedia:

export function createLocalStream(callConfig){
    return new Promise(function(resolve, reject){
        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;

        if (navigator.getUserMedia) {
           navigator.getUserMedia(callConfig,
              function(stream) {
                 resolve(stream);                
              },
              function(err) {
                 reject("The following error occured: " + err.name);
              }
           );
        } else {
           reject("getUserMedia not supported");
        }
    })
}

【问题讨论】:

    标签: javascript reactjs redux immutable.js


    【解决方案1】:

    你正在这样做:

    export default function(state = Map(), action){
        switch(action.type) {
            case 'GET_LOCAL_VIDEO':
                return getLocalVideo(state, action.config);
        }
        return state;
    }
    

    虽然预期 getLocalVideo 会返回新状态,但事实并非如此,这就是状态未定义的原因。您正在修改您的承诺中的状态,您不应该这样做。相反,尝试在“getLocalVideo”函数中执行异步操作,为不同状态调用操作(GET_LOCAL_VIDEO、GET_LOCAL_VIDEO_SUCCESS、GET_LOCAL_VIDEO_FAIL)

    这样的东西应该可以工作(别忘了调整你的减速器)

    export function getLocalVideo(config) {
      dispatch({type: 'GET_LOCAL_VIDEO', config});
      createLocalStream(config).then((stream)=>
          dispatch({
              type: 'GET_LOCAL_VIDEO_SUCCESS',
              localStreamInfo: Map({
                  localStream: stream,
                  localStreamURL: URL.createObjectURL(stream)
              })
          })
      }).catch((error)=>dispatch({type:'GET_LOCAL_VIDEO_FAIL', error}))
    

    【讨论】:

    • 感谢昆博。我应该将此 getLocalVideo 函数移动到我的动作创建者文件中还是应该保留在减速器中?
    • 您有多种选择。 1. 您可以将它放在动作创建者文件中(大多数人可能会这样做)。 2. 你可以把它放到自己的文件中(比如/lib/local-stream.js),然后在action creator中导入(这可以被认为是最干净的选项)。 3. 您可以将所有内容(动作类型、动作和减速器)放在一个文件中,如下所述:github.com/erikras/ducks-modular-redux(这可能是最舒适的选择)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多