简体   繁体   中英

State management in React component when the business logic is outside of the component

there! The App component is a container for three different components:

  • Map renders a map with visual marks on it representing addresses the user has provide.

  • List component contains all added addresses as list items.

  • Input allows a user to add a new address (in my terms that is called LocationPoint ).

Right now, the App keeps locations array in state with all those addresses ( LocationPoints ) and passes that array into all child components.

Manipulations with LocationPoints (add/move/update/deleteLocationPoint) are taken out to separate function as they are quite generic and may be reused somewhere else later.

But because those functions do not know about state existence I have to create some kind of "provider" functions that calls those actions (addLocationPoint, deleteLocationPoint, etc). Eg addLocationPoint func has to be called inside App.addLocationPoint .

The following example should explain what I was talking about better. Note: snippet doesn't work as it's not a real implementation.

 // Adds a new location point const addLocactionPoint = (locations: array, address: string) => { // ... return updatedLocations; } class App extends React.Component { constructor() { this.state = { locations: [], } // bind addLocPoint, etc. } addLocPoint(address) { this.setState(state => { addLocactionPoint(state.locations, address); }); } // ... render() { return ( <Input onSubmit={ this.addLocPoint } /> <List onDrag={ this.moveLocPoint } onDelete={ this.deleteLocPoint } /> <Map data={ this.state.locations } /> ); } } 

Can my approach be considered as a good practice? Or there are other ways to reduce amount of logic in App component and to avoid creating those "providers" without using state management libs (MobX, Redux, etc). Maybe the case I consider is a right time to introduce a Redux or MobX?

I'll be really grateful for advice or recommendations or links to explore on this question.

It's already good enough, this is how global state is usually maintained in vanilla React with no state management libraries. Context API may additionally be used to pass the state to nested components.

The thing that can be changed is that functions that update the state can actually be extracted and used as setState higher-order updater functions:

const addLocationPoint = (address) => ({ location }) => {
  // ...
  return updatedLocations;
}

class App extends React.Component {
  ...
  addLocPoint(address) {
    this.setState(addLocationPoint(address));
  }
  ...

A similar idea is used in Redux action creators.

In order for state updaters to provide real improvements, they have to be moved to another module. In this case they can be tested separately from a component that uses them and mocked with jest.mock in a component that uses them.

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