简体   繁体   中英

Reusing react/redux component on different routes connected to different part of state

I am running into a problem because I have a fairly complex component that renders a list of items. The list of items is taken directly from the redux state tree. I want to have 2 separate routes that reuse this same component, but each of them will connect to a different list from the state tree.

Here is a simplified example:

Starting with the state tree:

state = {
    fruits: ['apple', 'banana', 'grape', 'pear'],
    vegetables: ['celery', 'carrot', 'cucumber']
}

and a simple listing component

class ListView extends Component {
  render() {
    return (
      <div>
        {this.props.items.map((item, index) => 
          <div key={index}>{item}</div>
        )}
      </div>
    )
  }
}

function mapStateToProps(state) {
  return {
    items: state.fruits
  }
}

export default connect(mapStateToProps)(ListView)

The higher level App component looks like this:

class App extends Component {
  render() {
    return (
      <div>
        {this.props.children}
      </div>
    )
  }
}

export default connect()(App)

And the routes look like this:

  <Route path='/' component={App}>
    <IndexRedirect to='fruits' />
    <Route path='fruits' component={ListView} />
    <Route path='vegetables' component={ListView} />
  </Route>

So right now the ListView component is connected to the fruits part of the redux state. However I would like to utilize the route structure here so '/fruits' and '/vegetables' will both use the same component, but '/fruits' will list the fruits while '/vegetables' will list the vegetables.

The obvious work around is to create a completely new and identical component class and change the mapStateToProps method to connect to the vegetables array.

Is there a way to reuse this component but have access to different parts of the state tree in each?

From your ListView, you could export both FruitsList and VeggiesList as separate components, then display the correct one based on route.

class ListView extends Component {
  render() {
    return (
      <div>
        {this.props.items.map((item, index) => 
          <div key={index}>{item}</div>
        )}
      </div>
    )
  }
}

function mapStateToPropsVeggies(state) {
  return {
    items: state.veggies
  }
}

function mapStateToPropsFruits(state) {
  return {
    items: state.fruits
  }
}

const VeggiesList = connect(mapStateToPropsVeggies)(ListView);
const FruitsList = connect(mapStateToPropsFruits)(ListView);

export default ListView;
export {
    VeggiesList,
    FruitsList
};

Then update the router to:

<Route path='/' component={App}>
  <IndexRedirect to='fruits' />
  <Route path='fruits' component={FruitsList} />
  <Route path='vegetables' component={VeggiesList} />
</Route>

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