【问题标题】:How call React's setState function from outside of any component, like a utility function?如何从任何组件外部调用 React 的 setState 函数,比如实用函数?
【发布时间】:2025-12-07 17:55:01
【问题描述】:

我有一个应用程序,我想将读取、写入操作移动到实用程序文件,即远离组件。我正在尝试这样做。

component.js

import { saveData } from './utils/fileSave.js';

class App extends Component {
    saveContent() {
        saveData(this.setState, data);
    }
    ...
}

utils/fileSave.js

const saveData = (setState, data) => {
    setState(data);
}

但是,这会导致错误,说“TypeError: Cannot read property 'updater' of undefined”

不确定这是否是正确的方法。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您似乎需要在将setState 传递给外部函数之前对其进行绑定。

    saveData(this.setState.bind(this), data);

    【讨论】:

    • 顺便说一句,我认为saveData 让事情变得不清楚。 this.setState(data) 更好
    【解决方案2】:

    需要将this绑定到setState

     saveData(this.setState.bind(this), data);
    

    工作codesandbox demo

    【讨论】:

    • 箭头函数不像你描述的那样工作。您没有删除调用上下文,因为没有。它被称为saveData(...),而不是saveData.call(this, ...)
    • @estus 箭头函数始终指的是global this 这里的词法范围
    • this 未在您发布的代码中使用,因此常规 vs 箭头不会影响任何内容。
    • 当 setState 被调用时除了 setState 什么都没有,在 setState 内部调用this.somefun。现在这里this 将引用全局的。我指向这里
    • 这样不行。您可以尝试您提出的代码。原来的和这个都会失败。
    【解决方案3】:

    将依赖于上下文(组件实例)的方法提取到实用程序函数中并不是一个好主意,主要是因为这需要采取额外的操作才能使它们工作。

    由于this.setState 是作为回调传递的,它应该绑定到适当的上下文:

    saveData(this.setState.bind(this), data);
    

    或者实用函数应该被定义为常规函数并且在适当的上下文中被调用:

    function saveData(data) {
        this.setState(data);
    }
    
    class App extends Component {
        saveContent() {
            saveData.call(this, data);
        }
        ...
    }
    

    在这种情况下,继承更可取,因为它允许自然地获取适当的上下文。 saveData 可以通过 mixin 重用。

    可以直接赋值给类原型:

    function saveData(data) {
        this.setState(data);
    }
    
    class App extends Component {
        // saveData = saveData
        // is less efficient but also a correct way to do this
        saveContent() {
            this.saveData(data);
        }
        ...
    }
    App.prototype.saveData = saveData;
    

    或者通过装饰器应用:

    function saveData(target) {
        return class extends target {
            saveData(data) {
                this.setState(data);
            }
        }
    }
    
    
    @saveData
    class App extends Component {
        saveContent() {
            this.saveData(data);
        }
        ...
    }
    

    【讨论】:

      【解决方案4】:

      将绑定函数替换为箭头函数将允许它像回调一样工作。

      saveData((newState) => this.setState(newState), data);
      

      【讨论】: