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

IT技术 reactjs webpack
2021-05-08 23:10:09

我正在使用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

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

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个回答

这可能是 React 的一个错误。显然,结合 enqueueSetState 和 enqueueCallback 功能是一个主要的错误修复,但这些是早期版本的 React 中单独运行的调用。

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

在导入 npm module时,有时它们会引入不同版本的 React 作为依赖项,从而使用 setState 和回调创建此类不一致的错误。

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

当您设置状态时,请这样做。

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

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

您可以(也许实际上应该)从 componentDidUpdate 调用 getData 方法。它也会在状态改变后 100% 发生,并且(恕我直言)会让你的代码少一点回调地狱。

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

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

你提到的回调被从成功调用handleLookupChange,是否正确?

那么handleChangehandleLookupChangeonEnter事件被触发成功调用并且成功设置了 的值,对state吗?这个值state要么是

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

或者

{displayText : newValue}.

所以这是一种可能性。

我注意到handleLookupChange将两个值作为参数来自onEnter而不是event. 听起来您说该onEnter事件成功地将两个参数传递给handleLookupChangestate根据它们正确设置如果不是,我的猜测handleLookupChange应该是将event和处理它传递给handleChange.

或者另一个。

如果该转换成功发生,这是否是事件发生后如何从输入接收值的问题onEnter

当您使用 触发handleLookupChangeonEnter,是否有可能在输入中没有文本的情况下点击 enter 以某种方式返回 newValue 而不是作为null空字符串?这会导致displayText被设置为newValue(因为它不为空),从而导致displayText被设置为空字符串,导致回调addItemif语句永远不会触发和运行?

您是否检查addItem过确定没有在if语句上方调用

要检查的另一件事是dataSourceat是否selectedIndex可能正在获取空字符串,这可能会触发if语句不运行addItem.