没有为外部(npm打包)组件调用React setState回调

时间:2018-01-07 06:15:34

标签: reactjs webpack

我正在使用setState进行回调,以确保在状态更新后运行。

...
    this.setState({enabled : true},this.getData);
}
getData () {
    const self = this;
    fetch(this.props.url,{
        method : 'post',
        body : this.state
    }).then(function (response) {
        return response.json();
    }).then(function (result) {
        self.update();
    });
}
...

setState正在被召唤。 this.state.enabled确实已更改为true。但是,this.getData未被调用。

我觉得有趣的一点是,我正在通过npm包使用的组件正在发生这种情况。在我自己的代码中,带有回调的setState按设计工作。

所述外部组件也由我包装。我正在使用webpack来构建它。我的webpack配置可能有问题吗?

这是:

const Webpack = require('webpack');
const path = require('path');

module.exports = {
  entry: {
    index : './src/index.js'
  },
  output: {
    path: path.join(__dirname,'dist'),
    filename: '[name].js',
    library : 'TextField',
    libraryTarget: 'umd'
  },
  externals : [
    {
      'react' : {
        root : 'React',
        commonjs2 : 'react',
        commonjs : 'react',
        amd : 'react'
      }
    }
  ],
  module: {
      loaders: [
          { test: /\.(js?)$/, exclude: /node_modules/, loader: require.resolve('babel-loader'), query: {cacheDirectory: true, presets: ['es2015', 'react', 'stage-2']} }
      ]
  },
  devtool : 'eval'
};

编辑:

所以现在我非常确定当我从包中使用我的组件时会发生一些可疑的事情,当我从我的源代码中使用它时。

当我从作为源代码一部分的组件中调用setState时,这就是所谓的:

ReactComponent.prototype.setState = function (partialState, callback) {
    !(typeof partialState === 'object'
    || typeof partialState === 'function' 
    || partialState == null) ?
        process.env.NODE_ENV !== 'production' ? 
            invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.')
        : _prodInvariant('85')
    : void 0;
    this.updater.enqueueSetState(this, partialState);
    if (callback) {
        this.updater.enqueueCallback(this, callback, 'setState');
    }
};

以上内容来自名为ReactBaseClasses.js

的文件

当我从打包为npm包的组件中调用setState时,这就是所谓的:

Component.prototype.setState = function (partialState, callback) {
    !(typeof partialState === 'object'
      || typeof partialState === 'function'
      || partialState == null) ?
        invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.')
        : void 0;
    this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

以上内容来自名为react.development.js的文件。请注意,回调传递给enqueueSetState。有趣的是,当我进入enqueueSetState时,该函数对回调没有任何作用:

enqueueSetState: function (publicInstance, partialState) {
    if (process.env.NODE_ENV !== 'production') {
        ReactInstrumentation.debugTool.onSetState();
        process.env.NODE_ENV !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;
    }

    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');

    if (!internalInstance) {
        return;
    }

    var queue = internalInstance._pendingStateQueue || 
    (internalInstance._pendingStateQueue = []);
    queue.push(partialState);

    enqueueUpdate(internalInstance);
},

4 个答案:

答案 0 :(得分:2)

这可能是React的错误。显然,将enqueueSetState和enqueueCallback功能组合在一起是一个重大错误修复,但这些是在早期版本的React中单独运行的调用。

https://github.com/facebook/react/issues/8577

导入npm模块时,有时会将不同版本的React作为依赖项引入,使用setState和callbacks创建这些不一致的错误。

https://github.com/facebook/react/issues/10320

答案 1 :(得分:1)

您可以(也许实际应该)从componentDidUpdate调用getData方法。在状态发生变化后,它也会100%发生,而(恕我直言)会使你的代码变得更少回调地狱。

更新以下评论: 您可以将之前的状态/道具与componentDidUpdate中的当前状态/道具进行比较,然后根据需要调用您的方法:

componentDidUpdate(prevProps, prevState) {
  if (prevProps.something !== this.props.something) {
    // do some magic
  }
}

答案 2 :(得分:1)

设置状态时,请执行此操作。

this.setState({enabled : true}, () => { this.getData() });

() => {}绑定this到它的词汇父上下文。

答案 3 :(得分:1)

您提到从handleLookupChange成功调用了回调 ,对吗?

在触发handleChange事件并成功设置handleLookupChange的值后,onEnter成功调用了state,对吗? state的值为

{displayText : self.props.dataSource[selectedIndex]}

{displayText : newValue}.

所以这是一种可能性。

我注意到handleLookupChangeonEnter而不是event获取了两个值作为参数。听起来你说onEnter事件成功地将两个参数传递给handleLookupChange并根据它们正确设置state。如果不是,我的猜测是handleLookupChange应该event并处理它以传递给handleChange

或另一个。

如果成功进行了此转换,那么在onEnter事件之后如何从输入中接收值可能是一个问题吗?

当您使用handleLookupChange触发onEnter时,是否有可能在输入中没有文本的情况下以某种方式返回newValue而不是null而是作为空字符串?这会导致displayText设置为newValue(因为它不为空),从而导致displayText被设置为空字符串,从而导致回调addItem&# 39; s if语句永远不会触发并运行?

您是否检查过addItem是否确定未在if声明之上调用?

要检查的另一件事是dataSource selectedIndex是否可能拾取空字符串,这可能会触发if语句无法运行addItem内部