简体   繁体   English

在回调中调度 redux 动作

[英]Dispatch redux action in callback

I have started working with redux in react-native and I encountered problem, when I am dispatching action in onLoadStart function for Image component, the callback is firing and I see that action is called and I see Loading... on screen, but when I am dispatching in onLoadEnd function nothing happen (callback loadEnd is not fired, app looks like frozen) .我已经开始在 react-native 中使用 redux 并且遇到了问题,当我在onLoadStart函数中为 Image 组件dispatching动作时,回调正在触发,我看到该动作被调用,我在屏幕上看到Loading... ,但是当我在onLoadEnd函数中dispatching什么也没发生(callback loadEnd is not fired, app looks like frozen) When I use console.log in both places code is working fine.当我在两个地方都使用 console.log 时,代码工作正常。 Could someone tell me what am I doing wrong?有人能告诉我我做错了什么吗?

 class DisplayImage extends Component {

    loadStart() {
      this.props.iLoadingFunction(true);
    }
    loadEnd() {  // <- this function is not fired
      this.props.iLoadingFunction(false);
    }

    render() {
        if (this.props.isLoading) {
            return <Text>Loading…</Text>;
        }
        return (
          <View>
              <Image
                source={{uri: 'https://test.com/image'}}
                onLoadStart={this.loadStart.bind(this)}
                onLoadEnd={this.loadEnd.bind(this)}
               />
          </View>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        isLoading: state.isLoading
    };
};
const mapDispatchToProps = (dispatch) => {
    return bindActionCreators({ iLoadingFunction }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(DisplayImage);

action and reducer动作和减速器

export function iLoadingFunction(bool) {
    return {
        type: 'IS_LOADING',
        isLoading: bool
    };
}

export function iLoadingFunction(state = false, action) {
    switch (action.type) {
        case 'IS_LOADING':
            return action.isLoading;
        default:
            return state;
    }
}

I think the issue is coming from the order that actions and renders are occurring in. Let's look at the render function:我认为问题来自动作和渲染发生的顺序。让我们看看render函数:

render() {
    if (this.props.isLoading) {
        return <Text>Loading…</Text>;
    }
    return (
      <View>
          <Image
            source={{uri: 'https://test.com/image'}}
            onLoadStart={this.loadStart.bind(this)}
            onLoadEnd={this.loadEnd.bind(this)}
           />
      </View>
    );
}

The first time the component mounts this.props.isLoading is false , so the component renders组件第一次挂载this.props.isLoadingfalse ,所以组件渲染

<View>
    <Image
      source={{uri: 'https://test.com/image'}}
      onLoadStart={this.loadStart.bind(this)}
      onLoadEnd={this.loadEnd.bind(this)}
     />
</View>

The Image mounts, begins loading the image and dispatches this.props.iLoadingFunction(true) . Image挂载,开始加载图像并分派this.props.iLoadingFunction(true)

At this point isLoading updates in the store are triggers a re-render of the component.此时isLoading updates in the store 会触发组件的重新渲染。 This time this.props.isLoading is true so the component renders这次this.props.isLoading为真,所以组件渲染

<Text>Loading…</Text>

Now the original Image has been removed from the hierarchy.现在原始Image已从层次结构中删除。 I'm not actually sure if it continues to download the image, but the onLoadEnd handler does not fire as the component expecting to handle it has been removed.我实际上不确定它是否会继续下载图像,但是onLoadEnd处理程序不会触发,因为期望处理它的组件已被删除。

To get around this, I would leave the Image in the hierarchy and just include or exclude the Text based on this.props.isLoading , like so为了解决这个问题,我会将Image留在层次结构中,只包含或排除基于this.props.isLoadingText ,就像这样

render() {
    return (
      <View>
          { this.props.isLoading && <Text>Loading…</Text> }
          <Image
            source={{uri: 'https://test.com/image'}}
            onLoadStart={this.loadStart.bind(this)}
            onLoadEnd={this.loadEnd.bind(this)}
           />
      </View>
    );
}

The best solution to use callbackable-actions standardized actions.使用可回调动作标准化动作的最佳解决方案。 I recommend using the redux-cool package to do that我建议使用redux-cool包来做到这一点

npm install redux-cool
import {actionsCreator} from "redux-cool"
const callback = () => {
    console.log("Hello, I am callback!!!")
}
const callbackable_action = actionsCreator.CALLBACKABLE.EXAMPLE(1, 2, 3, callback)
console.log(callbackable_action)
//      {
//          type: "CALLBACKABLE/EXAMPLE",
//          args: [1, 2, 3],
//          cb: [[Function callback]],
//          _index: 1
//      }
callbackable_action.cb()
//      "Hello, I am callback!!!"

for more info, see: Redux Cool有关更多信息,请参阅: Redux Cool

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM