简体   繁体   English

如何在反应原生导航中正确使用redux

[英]How to properly use redux with react-native navigation

I have been trying to do a setup using react-native-router-flux and followed the steps. 我一直在尝试使用react-native-router-flux进行设置并按照步骤进行操作。 Then tried to follow the examples and also logging a lot of info to try to reverse engineer it to work. 然后尝试按照示例进行操作,并记录大量信息以尝试对其进行反向工程。 However even following all the information I could find I ended up with some weird state structure: 然而,即使遵循我可以找到的所有信息,我最终得到了一些奇怪的状态结构:

在此输入图像描述

scene is a object containing the router state. scene是包含路由器状态的对象。 However initial state is replicated inside scene (so it contains again devices and rooms objects). 但是,初始状态在scene内复制(因此它再次包含devicesrooms对象)。

If I change the ordinary state devices or routes it throws an error as: Key <name of the key> has already been defined (other people reporting the same problems here ). 如果我更改普通状态设备或路由,则会抛出错误: Key <name of the key> has already been defined (其他人在报告相同的问题)。

So my question is: How do you route your react native apps with redux? 所以我的问题是:你如何使用redux路由你的本机应用程序? Do you use other libraries? 你使用其他图书馆吗? Are there any examples or documented resources I could use to fix my code? 我可以使用任何示例或文档资源来修复我的代码吗?

Think that it has a typical redux structure. 认为它具有典型的redux结构。 For the sake of the example, this is how it looks on my app/index.js : 为了示例,这是它在我的app/index.js上的外观:

import React, { Component } from 'react'
import { Router, Scene } from 'react-native-router-flux'
import { createStore, applyMiddleware, compose } from 'redux'
import { Provider, connect } from 'react-redux'
import logger from 'redux-logger'

import reducers from './reducers'
import Home from './components/home'
import Device from './components/devices'
import Login from './components/login'

const middleware = [logger()]
const store = compose(
  applyMiddleware(...middleware)
)(createStore)(reducers)

const RouterWithRedux = connect(reducers)(Router)

export default class AppContainer extends Component {
  render () {
    return (
      <Provider store={store}>
        <RouterWithRedux>
          <Scene key='login' component={Login} title='Login' />
            <Scene key='root' initial={true}>
            <Scene key='home' component={Home} title='Home' />
            <Scene key='device' component={Device} title='Device' />
          </Scene>
        </RouterWithRedux>
      </Provider>
    )
  }
}

by my suffering experiences, there is no way to prevent Router re-render if you wrap it under a Provider and listen updates from redux , it is a nature by design. 根据我的痛苦经历,如果你把它包装在一个Provider并且从redux监听更新,就没有办法阻止Router重新渲染,这是设计的本质。

the point how to prevent this, is: Router should render once and just once it means: 如何防止这种情况,是: Router应该渲染一次,只需一次就意味着:

If you didn't connect to redux at all, it works fine since your Router would not be triggered by any of updates from redux. 如果您根本没有连接到redux,它可以正常工作,因为您的Router不会被redux的任何更新触发。

Also, you can connect() Router to redux to get a dispatch() method props but you can NOT listen to another props. 另外,你可以connect() Routerredux来获取一个dispatch()方法道具,但你不能听另一个道具。

Thus, the architecture would be: 因此,架构将是:

import {
    Router,
    Scene,
    Actions,
} from 'react-native-router-flux';


// --- child component can connect and listen to props they want.
const myConnectedMainConponent = connect()(myMainConponent);
const myConnectedLoginConponent = connect()(myLoginConponent);

// --- Create it via Actions.create(), or it will be re-created for each render of your Router
const scenes = Actions.create(
    <Scene key="root">
        <Scene key="login" component={myLoginConponent} />
        <Scene key="main" component={myMainConponent} />
    </Scene>
);

// --- Create connected Router if you want dispatch() method.
// --- Or you can just use vanilla Router
const myConnectedRouter = connect()(Router);

// --- your exported main router
export default class MyExportedRouter extends React.Component {
    constructor(props) {
        super(props);
    };

    render() {
        return (
            <Provider store={store}>
                <myConnectedRouter scenes={scenes} />
            </Provider>
        );
    }
}

ps I typed above codes directly here, be aware the syntax error :) ps我直接输入上面的代码,请注意语法错误:)

Point Taken: 采取的点:

  1. Router should render once and just once ( connect to get dispatch method only or not connect at all ) Router应该只渲染一次(连接只获取调度方法或根本不连接)
  2. pre create scenes via Actions.create() and pass it into Router 通过Actions.create()预创建场景并将其传递给路由器
  3. move your app main logic into one of the children of Router 将您的应用主逻辑移动到路由器的其中一个子节点

===================== =====================

this is originally replied on https://github.com/aksonov/react-native-router-flux/issues/376#issuecomment-241965769 这最初是在https://github.com/aksonov/react-native-router-flux/issues/376#issuecomment-241965769上回复的

thanks @jsdario for mention here, hope this helps 感谢@jsdario在这里提一下,希望这会有所帮助

I'm using only redux and react-redux . 我只使用reduxreact-redux Creating a store with createStore with some middlewares (after doing combineReducers ): 使用带有一些中间件的createStore创建商店(在执行combineReducers ):

const store = createStore(
  rootReducer,
  compose(applyMiddleware(thunk, promiseMiddleware())),
);

Registering app: 注册应用:

AppRegistry.registerComponent('app', () => () => (
  <Provider store={store}>
    <MainComponent />
  </Provider>
));

Using state in components: 在组件中使用state:

const mapStateToProps = (state) => ({
  isLoading: state.core.isLoading,
});

Connecting component to state using connect : 使用connect组件连接到状态:

export default connect(mapStateToProps)(HomeScene);

You can now also use NavigationExperimental directly from react-native. 您现在也可以直接从react-native使用NavigationExperimental

You can find more about it on this link . 您可以在此链接上找到更多相关信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM