简体   繁体   中英

React - Setting component state using a function outside of state, is it wrong?

Is it wrong to use setState in a function outside of the React component?

Example:

// myFunction.js
function myFunction() {
  ...
  this.setState({ ... })
}

// App.js
import myFunction from './myFunction

class App extends Component {
  constructor() {
    super()
    this.myFunction = myFunction.bind(this)
  }

  ...
}

I'm not sure the way you're binding will actually work. You could do something like:

export const getName = (klass) => {
  klass.setState({ name: 'Colin'})
}

then

class App extends Component {
  state = {
    name: 'React'
  };

  handleClick = () => {
    getName(this);
  }

  render() {
    return (
      <div>
        <p>{this.state.name}</p>
        <button onClick={this.handleClick}>change name</button>
      </div>
    );
  }
}

Working example here .

So the only reasons to do this is if you are reducing repeated code, eg two components use the same logic before calling this.setState , or if you want to make testing easier by having a separate pure function to test. For this reason I recommend not calling this.setState in your outside function, but rather returning the object you need so it can you can call this.setState on it.

function calculateSomeState(data) {
  // ...
  return { updated: data };
}

class MyComponent extends React.Component {
    constructor(props) {
      super(props)
      this.state = calculateSomeState(props.data);
    }

    handleChange = (e) => {
        const value = e.target.value;
        this.setState(calculateSomeState({ ...props.data, value }));
    }
}

It looks like a bug waiting to happen... If you want to use an external function to set state, you can use the alternative syntax provided by React:

this.setState((prevState, props)  => {
  return updatedState; //can be a partial state, like in the regular setState
});

That callback can easily be extracted to an external function and it's guaranteed to work

It is not wrong, the function is never called outside the component. This is a mix-in technique. bind isn't needed, as long as the function isn't used as a callback. In this case myFunction is same among all instances, a more efficient way would be:

class App extends Component {}
App.prototype.myFunction = myFunction;

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