如何注入改变组件状态的函数?

How to inject functions that change component state?

我想在我的组件之外保留一些功能以便于测试。但是,我无法使用这些函数更改状态,因为它们无法直接引用组件的状态。

所以我目前有一个 hacky 解决方案,我将函数设置为一个变量然后调用 this.setState。有没有更好的convention/more有效方法来做到这一点?

Tester.js中的示例函数代码:

const tester = () => {
  return 'new data';
}

export default tester;

App.js 中的示例组件代码(无导入):

class App extends Component {
    constructor() {
        super();
        this.state = {
            data: ''
        }
    }

    componentDidMount(){
        let newData = tester();
        this.setState({ data: newData })
    }

    render() {
        return(
            <div>{this.state.data}</div>
        )
    }
}

你可以像这样绑定你的测试函数(这种方法不适用于箭头函数):

function tester() {
  this.setState({ data: 'new Data' });
}

class App extends Component {
  constructor() {
    super();
    this.state = {
      data: '',
    };
    this.tester = tester.bind(this);
  }

  componentDidMount() {
    this.tester();
  }

  render() {
    return (
      <div>{this.state.data}</div>
    );
  }
}

但我更喜欢一种更简洁的方法,您不需要函数来访问 this(也适用于箭头函数):

function tester(prevState, props) {
  return {
    ...prevState,
    data: 'new Data',
  };
}

class App extends Component {
  constructor() {
    super();
    this.state = {
      data: '',
    };
  }

  componentDidMount() {
    this.setState(tester);
  }

  render() {
    return (
      <div>{this.state.data}</div>
    );
  }
}

You can pass a function to setState() 将 return 一个表示组件新状态的新对象。所以你可以这样做:

const tester = (previousState, props) => {
  return {
    ...previousState,
    data: 'new data',
  };
}

class App extends Component {
    constructor() {
        super();
        this.state = {
            data: ''
        }
    }

    componentDidMount(){
        this.setState(tester)
    }

    render() {
        return(
            <div>{this.state.data}</div>
        )
    }
}

原因是您现在可以在 tester 函数中访问组件的先前状态和道具。

如果您只需要访问应用内不变的 static 占位符值,例如 Lorem Ipsum 或其他,那么只需将数据导出为 JSON对象并像这样使用它:

// testData.js
export const testData = {
  foo: "bar",
  baz: 7,
};

...

// In your app.jsx file
import testData from "./testData.js";

const qux = testData.foo; // "bar"

etc.