如何在react-navigation中使用用户指定的主题?

时间:2017-11-02 09:17:36

标签: react-native redux react-navigation

我一直试图设想我的反应导航导航器,使用硬编码颜色(Colours.backgroundColours.accent很容易。

当用户通过身份验证时,我会提供他们的基本详细信息和主题对象。这将使用redux(state.auth.user.theme

存储在我的应用状态中

我有一个AppNavigation,用于创建导航器。

AppNavigation.js

import React from 'react'
import { Text, Animated, Easing, Image, View } from 'react-native'
import { StackNavigator, DrawerNavigator, addNavigationHelpers } from 'react-navigation'
import Icon from 'react-native-vector-icons/EvilIcons'
import { connect } from 'react-redux'

import DrawerContainer from '../Containers/DrawerContainer'
import ScreenTwoScreen from '../Containers/ScreenTwoScreen'
import ScreenOneScreen from '../Containers/ScreenOneScreen'
import DashboardScreen from '../Containers/DashboardScreen'
import LoginScreen from '../Containers/LoginScreen'

import styles from './Styles/NavigationStyles'
import ThemeProvider from '../Themes/ThemeProvider';
import Images from '../Themes/Images';

const Colors = ThemeProvider()

const DrawerStack = DrawerNavigator({
  screenOneScreen: { screen: ScreenOneScreen },
  dashboardScreen: { screen: DashboardScreen },
}, {
    gesturesEnabled: false,
    contentComponent: DrawerContainer
  })

const drawerButton = (navigation) =>
    <Text
      style={{ padding: 5, color: 'white' }}
      onPress={() => {
        // Coming soon: navigation.navigate('DrawerToggle')
        // https://github.com/react-community/react-navigation/pull/2492
        if (navigation.state.index === 0) {
          navigation.navigate('DrawerOpen')
        } else {
          navigation.navigate('DrawerClose')
        }
      }
      }><Icon name="navicon" color={Colors.headerText} size={24} /></Text>


// login stack
const LoginStack = StackNavigator({
  loginScreen: { screen: LoginScreen },
}, {
    headerMode: 'none',
    navigationOptions: {
    }
  })

const logoStyle = {
  height: 45,
  width: 45,
  marginLeft: 10,
  resizeMode: 'contain'
}
const DrawerNavigation = StackNavigator({
  DrawerStack: { screen: DrawerStack }
}, {
    headerMode: 'float',
    navigationOptions: ({ navigation }) => ({
      headerStyle: { backgroundColor: Colors.brand },
      title: 'Welcome!',
      headerTintColor: Colors.headerText,
      gesturesEnabled: false,
      headerRight: drawerButton(navigation),
      headerLeft: <Image source={Images.clubLogo} style={logoStyle} />
    })
  })


// Manifest of possible screens
const PrimaryNav = StackNavigator({
  loginStack: { screen: LoginStack },
  drawerStack: { screen: DrawerNavigation }
}, {
    // Default config for all screens
    headerMode: 'none',
    initialRouteName: 'loginStack',
    navigationOptions: {
      headerStyle: styles.header
    }
  })

export default PrimaryNav

这在ReduxNavigation.js中使用:

ReduxNavigation.js

import React from 'react'
import * as ReactNavigation from 'react-navigation';
import { connect } from 'react-redux'
import AppNavigation from './AppNavigation'
import Colors from '../Themes/Colors'
import ThemeProvider from '../Themes/ThemeProvider'
// here is our redux-aware our smart component
class ReduxNavigation extends React.Component {
  static navigationOptions = ({ navigation, screenProps }) => {
    console.log(navigation)
    return {
      headerStyle: {
        backgroundColor: this.props.user ? this.props.user.club.brand : Colors.brand
      }
    }
  }
  render() {
    const { dispatch, nav, user } = this.props
    const navigation = ReactNavigation.addNavigationHelpers({
      dispatch,
      state: nav
    })


    // if (user) {
    //   theme = ThemeProvider(user.club.theme)
    // }
    return <AppNavigation navigation={navigation} />
  }

}

const mapStateToProps = state => ({ nav: state.nav, user: state.auth.user })
export default connect(mapStateToProps)(ReduxNavigation)

ThemeProvider.js

没什么好看的:

import Colors from './Colors';

const ThemeProvider = (other ={}) => {
    return Object.assign({}, Colors, other)
}

export default ThemeProvider;

我尝试的事情

  • 创建了一个主题提供程序方法,将用户主题合并为颜色,它可以工作,但它不对。
  • 将AppNavigation的核心移动到ReduxNavigation的渲染方法中,但这使得应用程序无响应,这是可以理解的。
  • 试图找出一种将主题作为道具传递给PrimaryNav的方法,react-navigation并不喜欢额外的道具。

思想和想法?此外,应用的核心是InfiniteRed/ignite生成的,如果它有用的话。

1 个答案:

答案 0 :(得分:1)

在ReduxNavigation中使用screenProps找出一种方法:

class ReduxNavigation extends React.Component {

  render() {
    const { dispatch, nav, user } = this.props
    const navigation = ReactNavigation.addNavigationHelpers({
      dispatch,
      state: nav
    })
    return <AppNavigation navigation={navigation} screenProps={{ user }} />
  }

}

然后在我需要自定义主题的导航器的AppNavigation中:

DrawerNavigation = StackNavigator({
  DrawerStack: { screen: DrawerStack }
}, {
    headerMode: 'float',
    navigationOptions: ({ navigation, screenProps }) => {
      let headerText = Colors.headerText;
      let brand = Colors.brand;
      let accent = Colors.accent;
      if (screenProps.user) {
        let theme = screenProps.user.club.theme;
        brand = theme.brand;
        headerText = theme.headerText;
        accent = theme.accent;
      }
      return ({
        headerStyle: { backgroundColor: brand },
        title: 'Welcome!',
        headerTintColor: headerText,
        gesturesEnabled: false,
        headerRight: drawerButton(navigation, headerText),
        headerLeft: <Image source={Images.clubLogo} style={logoStyle} />
      })
    }
  })