最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How call React's setState function from outside of any component, like a utility function? - Stack Overflow

programmeradmin1浏览0评论

I have an app where I want to move the read, write operations to a utility file i.e. away from ponent. I am trying to do it this way.

ponent.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);
}

However, that leads to an error, saying 'TypeError: Cannot read property 'updater' of undefined'

Not sure if this is the correct way to go about it.

I have an app where I want to move the read, write operations to a utility file i.e. away from ponent. I am trying to do it this way.

ponent.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);
}

However, that leads to an error, saying 'TypeError: Cannot read property 'updater' of undefined'

Not sure if this is the correct way to go about it.

Share Improve this question asked Aug 1, 2018 at 9:46 purezenpurezen 64312 silver badges29 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 5

It looks like you need to bind setState before passing it to an external function.

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

Need to bind this to setState.

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

Working codesandbox demo

This is not a good idea to extract methods that rely on the context (ponent instance) to utility functions, primarily because this requires to take additional actions to make them work.

Since this.setState is passed as a callback, it should be either bound to proper context:

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

Or utility function should be defined as regular function and be called with proper context:

function saveData(data) {
    this.setState(data);
}

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

This is the case where inheritance is preferable because it allows to get proper context naturally. saveData can be reused via a mixin.

It can be assigned directly to class prototype:

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;

Or be applied via a decorator:

function saveData(target) {
    return class extends target {
        saveData(data) {
            this.setState(data);
        }
    }
}


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

Replace the bind function with arrow function will allow it works like a callback.

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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论