如何在代码中添加Redux实现?

时间:2019-01-23 08:41:40

标签: react-native redux react-redux

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

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

   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文件

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


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

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

下面显示了我的不同屏幕文件。   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

    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实现?

2 个答案:

答案 0 :(得分:0)

您检查了他们的文档吗? https://redux.js.org/ 此外,您还可以在react native应用https://github.com/infinitered/ignite

中看到为redux点燃样板实现

答案 1 :(得分:0)

将屏幕代码(jsx)与容器代码(在其中具有mapDispatchToProps和mapStateToProps)分开是一种好习惯。

因此,使用redux的良好“信息流”看起来像这样:

屏幕+容器-> (发送)-> 操作-> (发送)-> 减速器-> ,然后存储在商店中。

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

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 ,这是您的简化器,您也可以使用简化器来处理应用程序中的导航(尽管不推荐)。基本上,这是一个巨大的切换案例,您可以执行调度操作。

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标记中

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

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

希望这可以帮助您了解基本流程(我确定还有其他方法)以及如何根据需要实现redux。