Leon
Leon

Reputation: 562

Top level component root-Scene/Router react-native-router-flux

I'd like to add some "logic-component" to the top level of my scenes.

i.e I got that:

<Router>
    <Scene key="root" hideNavBar={true}>
        <Scene key="home" component={HomeContainer} />
        <Scene key="search" component={SearchContainer} />
        <Scene key="list" component={ListContainer} />
        ...
    </Scene>
</Router>

Each container is connected to Redux, using connect()(), and each got its own reducer that only itself need.

i.e:

export default connect(mapStateToProps, mapDispatchToProps)(HomeContainer)

So, what I'd need to do is to connect the "root" Scene to Redux and give it its general reducer (the one that also all the other scenes depends on). But with that, I want to use componentDidUpdate, componentWillReceiveProps, ... to listen to, i.e Netinfo when the connection changes, to update the reducer's state.

I'm not sure whether it's clear or not, I hope it is. If you need more informations just ask them.

Thanks for the help

Solution

Look at atlanteh's answer, and look at the docs it says everything needed :) https://github.com/aksonov/react-native-router-flux/tree/master/docs

My final solution where everything works as expected is:

const ConnectedRouter = connect()(Router)

const scenes = Actions.create(
    <Scene key="root" hideNavBar={true}>
        <Scene key="home" component={HomeContainer} />
    </Scene>
)

class ReduxRouter extends Component {
  componentWillReceiveProps(newProps) {
      if(!newProps.isConnected) {
          // logic
      }
  }
  render() {
    return (
      <ConnectedRouter scenes={scenes} {...this.props}/>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    // State
  }
}

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    // Actions
  }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(ReduxRouter);

It's basically a mix of everything I tried before and It works great! No "Key xxx is already defined" or whatsoever.

Upvotes: 2

Views: 1516

Answers (2)

Travis White
Travis White

Reputation: 1977

If you are updating the data in the store properly, any connected data should refresh.

If you can see the actions/reducer running but the connected components never re-render then you are most likely mutating state in the reducer and the connected component never notices the data change.

If you are modifying deeply nested properties in the store then I highly suggest ImmutableJS.

Upvotes: 0

atlanteh
atlanteh

Reputation: 5835

You can do something like this:

class MyRouter extends React.Component {
    componentWillReceiveProps(newProps) {
        if(!newProps.network.isActive) {
            // do something here
        }
    }
    render() {
        <Router>
            <Scene key="root" hideNavBar={true}>
                <Scene key="home" component={HomeContainer} networkActive={this.props.network.isActive} />
                <Scene key="search" component={SearchContainer} />
                <Scene key="list" component={ListContainer} />
                ...
            </Scene>  
        </Router>  
    }
}
const mapStateToProps = state => state;
export default connect(mapStateToProps)(MyRouter);

And you this component as your router, so now you have a Router that's connected to the state.

Notice that you can also connect react-native-router-flux to the state and it will dispatch the navigations it does:

const ConnectedRouter = connect()(Router);

Edit - Avoiding key already defined

To avoid key already defined, you can use:

const scenes = Actions.create(
   <Scene key="root" hideNavBar={true}>
        <Scene key="home" component={HomeContainer} networkActive={this.props.network.isActive} />
        <Scene key="search" component={SearchContainer} />
        <Scene key="list" component={ListContainer} />
        ...
    </Scene>  
)

and then in router:

<ConnectedRouter
   scenes={scenes}
 />

Upvotes: 3

Related Questions