简体   繁体   中英

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

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

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

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.

看起来您需要在将setState传递给外部函数之前绑定它。

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

用箭头函数替换绑定函数将使其像回调一样工作。

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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