如何在我的代码中添加 Redux 实现? [英] How do I add Redux implementation in my code?

查看:47
本文介绍了如何在我的代码中添加 Redux 实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过一些反应导航将 redux 实现添加到我的简单登录应用程序中.

I want to add redux implementation to my simple Login application with some react navigations.

这是我导入 AppDrawerNavigator 的 App.js 文件

This is my App.js file where I'm importing my AppDrawerNavigator

   import React, {Component} from 'react';
import {createAppContainer, createStackNavigator} from 'react-navigation';
import HomeScreen from './screens/HomeScreen.js';

/** Importing navigator */
import AppDrawerNavigator from './drawerNavigator';


class App extends React.Component {
    render() {
      return <AppContainer />;
    }
}

export default App;



const AppStackNavigator = createStackNavigator(
  {
    Home: {screen: HomeScreen},
    Welcome: AppDrawerNavigator
  },
  {
    initialRouteName: 'Home',
    headerMode: "none",
  }
);

const AppContainer = createAppContainer(AppStackNavigator);

这是我的 index.js 文件,指向我的主 App.js 文件

This is my index.js file pointing to my main App.js file

import {AppRegistry} from 'react-native';
import App from './App';


import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

下面显示了我的不同屏幕文件.HomeScreen.js

Below shows my different screen files. HomeScreen.js

    import React, {Component} from 'react';
import {
  Platform, 
  StyleSheet, 
  Text, 
  View, 
  TouchableOpacity, 
  Alert, 
  Keyboard, 
  TextInput,
} from 'react-native';
//HomeScreen
export default class HomeScreen extends React.Component {
  constructor(props) {
  super(props);
  this.state = {username: null, password: null, isPasswordHidden: true, toggleText: 'Show'};
}

handleToggle = () => {
  const { isPasswordHidden } = this.state;

  if (isPasswordHidden) {
    this.setState({isPasswordHidden: false});
    this.setState({toggleText: 'Hide'});
  } else {
    this.setState({isPasswordHidden: true});
    this.setState({toggleText: 'Show'});
  }
}

//Validate() to check whether the input username is in Mail format
validate = (inputValue) => {
  let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ; // Regex for Emails
  // let reg = /^(\+\d{1,3}[- ]?)?\d{10}$/; // Regex for phone numbers
  return reg.test(inputValue);
}
clearText(fieldName) {
  this.refs[fieldName].clear(0);
}

render() {
  return (
    <View style={styles.container}>
      <Text style={styles.welcome}></Text>


      <TextInput
        ref={'input1'}
        style={styles.input}
        placeholder="Username"
        onChangeText={value => this.setState({username: value})}
        // placeholderTextColor="Grey"
        // maxLength={13} // For Indian phone numbers
        // onChangeText={(text) => this.validate(text)}
        // value={this.state.username}
      />

      <TextInput
        ref={'input2'}
        style={styles.input}
        placeholder="Password"
        maxLength={10}
        secureTextEntry={this.state.isPasswordHidden}
        onChangeText={value => this.setState({password: value})}
        // placeholderTextColor="rgb(225,225,225)"
      />

      <TouchableOpacity
        onPress={this.handleToggle}
      >
        <Text>{this.state.toggleText}</Text>

      </TouchableOpacity>

      <View style={{padding: 20}}>
        <TouchableOpacity onPress={() => {

          if (!this.validate(this.state.username)) {
            Alert.alert("Invalid");
            Keyboard.dismiss();
          } else if (this.state.username === 'vinay@gmail.com' && this.state.password === 'password') {
            //Alert.alert("Login Successful");
            if(this.state.username && this.state.password){
              this.props.navigation.navigate('Welcome', {
                username: this.state.username,
                password: this.state.password,
              });
              this.setState({username: ""});
              this.setState({password: ""});
            }else{
              alert("Invalid");
            }

            Keyboard.dismiss();
            this.clearText('input1');
            this.clearText('input2');
          } else if (this.state.username === null && this.state.password === null) {
            Alert.alert("Invalid");
          } else {
            Alert.alert("Login Failed");
            this.clearText('input1');
            this.clearText('input2');
            Keyboard.dismiss();
          }

        }}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>LOGIN</Text>
          </View>
        </TouchableOpacity>
      </View>

    </View>
  );
}
}

/** Stylesheets Defined **/
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    // backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 40,
    margin: 10,
    padding: 20
    // textAlign: 'center',
  },
  input:{
    // height: 40,
    // margin: 10,
    width: 260,
    backgroundColor: 'lightgrey',
    marginBottom: 10,
    padding: 10,
    color: 'black'
  },
  button: {
    marginBottom: 30,
    width: 260,
    alignItems: 'center',
    backgroundColor: '#2196F3',
    fontWeight: 'bold'

  },
  buttonText: {
    padding: 20,
    color: 'white'
  }
});

这是屏幕 ProfileScreen.js

 import React, {Component} from 'react';
import {
  Platform, 
  StyleSheet, 
  Text, 
  Image,
  View, 
} from 'react-native';

export default class Profile extends Component {
    render() {
      return(
        <View>
          <Image 
          style={styles.image}
          source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
          />
        </View>
      );
    }
}

/** Stylesheets Defined **/
const styles = StyleSheet.create({
    container: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      // backgroundColor: '#F5FCFF',
    },
    welcome: {
      fontSize: 40,
      margin: 10,
      padding: 20
      // textAlign: 'center',
    },
    input:{
      // height: 40,
      // margin: 10,
      width: 260,
      backgroundColor: 'lightgrey',
      marginBottom: 10,
      padding: 10,
      color: 'black'
    },
    button: {
      marginBottom: 30,
      width: 260,
      alignItems: 'center',
      backgroundColor: '#2196F3',
      fontWeight: 'bold'

    },
    buttonText: {
      padding: 20,
      color: 'white'
    },
    image: {
      width: 200,
      height: 200,
      margin: 10
    }
});

这是屏幕 SettingsScreen.js

    import React, {Component} from 'react';
import {
  Platform, 
  StyleSheet, 
  Text, 
  View, 
} from 'react-native';

export default class Settings extends Component {
    render() {
      return(
        <View style={styles.container}>
          <Text>Settings</Text>
        </View>
      );
    }
}

/** Stylesheets Defined **/
const styles = StyleSheet.create({
    container: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      // backgroundColor: '#F5FCFF',
    },
    welcome: {
      fontSize: 40,
      margin: 10,
      padding: 20
      // textAlign: 'center',
    },
    input:{
      // height: 40,
      // margin: 10,
      width: 260,
      backgroundColor: 'lightgrey',
      marginBottom: 10,
      padding: 10,
      color: 'black'
    },
    button: {
      marginBottom: 30,
      width: 260,
      alignItems: 'center',
      backgroundColor: '#2196F3',
      fontWeight: 'bold'

    },
    buttonText: {
      padding: 20,
      color: 'white'
    }
});

这是屏幕 TabA.js

    import React, { Component } from 'react'
import {
  View,
  Text,
  StyleSheet,
} from 'react-native'

export default class TabA extends React.Component {

  // static navigationOptions = ({ navigation }) => ({
  //   title: 'Tab A',
  // })

  render () {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>I'm Tab A</Text>
      </View>
      )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#c0392b',
    padding: 20,
  },
  text: {
    color: 'white',
    fontSize: 40,
    fontWeight: 'bold',
  }
})

这是屏幕 TabB.js

    import React, { Component } from 'react'
import {
  View,
  Text,
  StyleSheet,
} from 'react-native'

export default class TabB extends React.Component {

  // static navigationOptions = ({ navigation }) => ({
  //   title: 'Tab B',
  // })

  render () {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>I'm Tab B</Text>
      </View>
      )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#8e44ad',
    padding: 20,
  },
  text: {
    color: 'white',
    fontSize: 40,
    fontWeight: 'bold',
  }
})

这是屏幕WelcomeScreen.js

    import React, {Component} from 'react';
import {
  Platform, 
  StyleSheet, 
  Text, 
  View, 
} from 'react-native';

export default class WelcomeScreen extends Component {

  render() {
    const { navigation } = this.props;
    const u_name = navigation.getParam('username', 'name');
    const p_word = navigation.getParam('password', 'word');
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>WELCOME</Text>
        <Text>USERNAME: {JSON.stringify(u_name)}</Text>
        <Text>PASSWORD: {JSON.stringify(p_word)}</Text>

        {/* <View style={{padding: 20}}>
          <Button style={{margin: 20}}
            title="LOGOUT"
            onPress={() => this.props.navigation.navigate('Home')}
          />
        </View> */}
      </View>
    );
  }
}

/** Stylesheets Defined **/
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    // backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 40,
    margin: 10,
    padding: 20
    // textAlign: 'center',
  },
  input:{
    // height: 40,
    // margin: 10,
    width: 260,
    backgroundColor: 'lightgrey',
    marginBottom: 10,
    padding: 10,
    color: 'black'
  },
  button: {
    marginBottom: 30,
    width: 260,
    alignItems: 'center',
    backgroundColor: '#2196F3',
    fontWeight: 'bold'

  },
  buttonText: {
    padding: 20,
    color: 'white'
  }
});

下面显示了我的不同导航器文件这是抽屉导航器文件 drawerNavigator.js

Below shows my different navigator files This is the drawer navigator file drawerNavigator.js

    import React, {Component} from 'react';
import {
    View, 
    Button, 
    SafeAreaView,
} from 'react-native';

import {
    createDrawerNavigator,
    DrawerItems,
} from 'react-navigation';

import TabA from './screens/TabA.js';
import TabB from './screens/TabB.js';
import WelcomeStackNavigator from './stackNavigator';

class Hidden extends React.Component {
    render() {
      return null;
    }
}

const AppDrawerNavigator = createDrawerNavigator({
    Welcome: { 
        screen: WelcomeStackNavigator,
        navigationOptions: {
            drawerLabel: <Hidden />
        } 
    },
    TabA: { screen: TabA },
    TabB: { screen: TabB },
    // TabC: { screen: TabC },
},{
    contentComponent:(props) => (
      <View style={{flex:1}}>
          <SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
              <DrawerItems {...props} />
              <Button 
                title="Logout" 
                onPress={() => {
                    props.navigation.navigate('Home')
                }}
              />
          </SafeAreaView>
      </View>
    ),
    drawerOpenRoute: 'DrawerOpen',
    drawerCloseRoute: 'DrawerClose',
    drawerToggleRoute: 'DrawerToggle'
})

export default AppDrawerNavigator;

这是堆栈导航器文件stackNavigator.js

import React, {Component} from 'react';
import Icon from 'react-native-vector-icons/Ionicons';

import {
  createStackNavigator,
} from 'react-navigation';

import WelcomeTabNavigator from './tabNavigator';

const WelcomeStackNavigator = createStackNavigator({
    WelcomeTabNavigator: WelcomeTabNavigator
  },
  {
    defaultNavigationOptions:({navigation}) => {
      return {
        headerLeft: (
          <Icon 
            style={{paddingLeft: 20}}
            onPress={() => navigation.openDrawer()}
            name="md-menu" 
            size={30}
          />
        )
      };
    }
  }
);

export default WelcomeStackNavigator;

这是标签导航器文件 tabNavigator.js

import React, {Component} from 'react';
import WelcomeScreen from './screens/WelcomeScreen.js';
import Profile from './screens/ProfileScreen.js';
import Settings from './screens/SettingsScreen.js';

import Icon from 'react-native-vector-icons/Ionicons';

import {
  createBottomTabNavigator,
} from 'react-navigation';

const WelcomeTabNavigator = createBottomTabNavigator(
    {
        Welcome: { 
            screen: WelcomeScreen,
            navigationOptions: {

                tabBarIcon: ({tintColor}) => (
                    <Icon
                        name="md-home"
                        size={20}
                    />
                )
            }
        },
        Profile: {
            screen: Profile,
            navigationOptions: {

                tabBarIcon: ({tintColor}) => (
                    <Icon
                        name="md-book"
                        size={20}
                    />
                )
            }
        },
        Settings: {
            screen: Settings,
            navigationOptions: {

                tabBarIcon: ({tintColor}) => (
                    <Icon
                        name="md-settings"
                        size={20}
                    />
                )
            }
        },
    }, 
    {
        tabBarOptions: {
            activeTintColor: '#fb9800',
            inactiveTintColor: '#7e7b7b',
            style: { height: 40,backgroundColor: '#fff',borderTopWidth:0.5,borderTopColor: '#7e7b7b' },
            labelStyle: {fontSize: 15}
        },
        // navigationOptions:({navigation}) => {
        //     const {routeName} = navigation.state.routes[navigation.state.index];
        //     return {
        //         headerTitle: routeName
        //     };
        // },
        navigationOptions:({navigation}) => {
            const {routeName} = navigation.state.routes[navigation.state.index];
            return {
                headerTitle: routeName,
                // headerLeft: (
                //     <Icon 
                //     style={{paddingLeft: 20}}
                //     onPress={() => navigation.openDrawer()}
                //     name="md-menu" 
                //     size={30}
                //     />
                // )
            };
        }
    }
)

export default WelcomeTabNavigator;

如何构建我的项目并在此登录应用程序上添加 redux 实现?

How do I structure my project and add redux implementation on this login application?

推荐答案

将您的屏幕代码 (jsx) 与您的容器代码(您将拥有 mapDispatchToProps 和 mapStateToProps)分开似乎是一个很好的做法.

It seems like a good practice to have your screen code(jsx) separated from your container code (where you'll have your mapDispatchToProps and your mapStateToProps).

因此,使用 redux 的良好信息流"如下所示:

So a good 'flow of information' using redux would look something like this:

屏幕+容器->(调度)->动作->(调度)->减速器-> 然后存储在商店中.

Screen + container -> (dispatch) -> actions -> (dispatch) -> reducers -> and then stored in the store.

为了让您了解如何实现这一点,我将展示一个示例,说明如何将其用于您的目的.

So to give you an idea of how to implement this, I'll show an example on how to use it for your purpose.

LoginScreen.js

export default class LoginScreen extends Component {
  constructor(props) {
    super(props);
  }

  login() {
  //Here i'm assuming that you have clicked some kind of button 
  //to submit the login information that you filled in your text input (username and password)

    const { username, password } = this.props;
    const loginData = {
      username,
      password
    }

    //here you'll be passing it to the dispatchToProps in your container
    this.props.login(loginData)
  }
}

LoginScreenContainer.js

const mapStateToProps = state => {
  ...state.userReducer,
}

const mapDispatchToProps = (dispatch) => {
  //The function that you called on your screen, 
  //and then we'll be dispatching the loginData to the user_actions

  login: (loginData) => {
    dispatch(loginUser(loginData))
  },
}

//Dont forget to connect both mapStateToProps and mapDispatchToProps to your screen
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);

User_Actions.js

export function loginUser(loginData) {
  //The code to login would be here, if you are using firebase, 
  //back4app or any other provider, you would implement the login required here

  //Now assuming that the user successfully logged on you would dispatch a success and then store that user in the store 
  //(just as an example, you can store the username and any other information that you'd like):
  if (user) {
    dispatch({ type: 'USER_LOGIN', payload: { user } })
  } else {
    dispatch({ type: 'USER_LOGIN_REJECTED' });
  }
}

User_Reducer.js 这是您的减速器,您也可以使用减速器来处理应用中的导航(虽然不推荐).这基本上是一个巨大的 switch 案例,您将获得调度操作.

User_Reducer.js this is your reducer, you can have reducers also to handle the navigation in your app (not recommended though). It's basically a giant switch case that you'll get the dispatch actions.

export default function reducer(state = {
  user: null,
}, action) {

  const { type, payload } = action
  switch (type) {

    case 'USER_LOGIN': {
      return { ...state, user: payload.user }
    }
    case 'USER_LOGIN_REJECTED': {
      return { ...state, user: null }
    }

    default: {
      return state
    }
  }
}

Store.js

const rootReducer = combineReducers({
  user_reducer,
})

let middleware = [thunk]
if (process.env.NODE_ENV !== 'production') {
  middleware = [...middleware, logger] //Logger is an useful library to log your state changes
}

export default createStore(
  rootReducer,
  undefined,
  applyMiddleware(...middleware)
)

App.js 然后在这里你将你的主要 stackNavigator 包装在 provider 标签中

App.js and then here you'll wrap your main stackNavigator in the provider tag

import { Provider } from 'react-redux';
import store from './src/redux/store';

render() {
  return (
    <Provider store={store}>
      <RootNavigator />
    </Provider>
  )
}

希望这能帮助您了解基本流程(我相信还有其他方法可以做到)以及如何根据您的需要实现 redux.

Hopefully this helps you understand a basic flow (I'm sure there are other ways to do it) and how to implement redux for your needs.

这篇关于如何在我的代码中添加 Redux 实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆