反应本机Redux导致整个页面在调用函数时呈现

时间:2019-05-17 07:03:36

标签: javascript reactjs react-native redux react-redux

我在使用React Native Redux时遇到问题,我从TextField内部的onChangeText函数调用Redux动作。通常,这样的更新只会导致TextField本身更新,但是每次调用该函数时都会重新呈现整个页面。
这是TextField的代码。有问题的方法是 this.props.updateURL(value)

<TextField label='Server'
                value={this.props.profile.url}
                labelFontSize={textFont(16)}
                tintColor='#B3B2B6'
                autoCapitalize="none"
                autoCorrect={false}
                returnKeyType={'next'}
                blurOnSubmit={false}
                autoFocus={!this.props.profile.edited}
                style={styles.inputStyle}
                selectionColor={CUSRSOR_COLOR}
                editable={!this.props.profile.edited}

                onChangeText={async value => {
                  this.props.updateURL(value)

                }}
                renderAccessory={()=>{
                  return(<TouchableOpacity onPress={this.handleScanPress} >
                    <Image source={ImgScan} style={{height: 25, width: 25, overflow:'visible', marginBottom:20, marginRight: 10}}/>
                  </TouchableOpacity>);
                }}
              >
              </TextField>

这用于Redux方法mapStateToProps和mapDispatchToProps:

const mapStateToProps = (state) => {
return {
    profile : state.profileReducer,
    deviceUid: state.GlobalReducer.deviceUid,
    locationsList: state.LogsReducer.locationList,
    errorList: state.ErrorsReducer.failedList,
    watermarkText: state.GlobalReducer.watermarkText,
    alertPresent: state.LogsReducer.alertPresent
}
};

const mapDispatchToProps = (dispatch) => {
    return {
        updateURL : (url) => dispatch(updateURL(url)),
        updateUserName : (userName) => dispatch(updateUserName(userName)),
        updatePassword : (password) => dispatch(updatePassword(password)),
        updateDeviceName : (deviceName) => dispatch(updateDeviceName(deviceName)),
        allFieldsEntered : (url,userName,password) => dispatch(allFieldsEntered(url,userName,password)),
        loginDevice: (url,userName,password,deviceName,deviceId,navigation,existingUser) => dispatch(callLoginApi(url,userName,password,deviceName,deviceId,navigation,existingUser)),
        updateFailureMessage: (message) => dispatch(updateFailureMessage(message)),
        showLoader: () => dispatch(showLoader()),
        hideLoader: () => dispatch(hideLoader()),
        updateRegistrationSuccess: (value) =>  dispatch(updateRegistrationSuccess(value)),
        checkForInternet: () => dispatch(checkConnectivity()),
        getProfileDetails: async(isToken) => await dispatch(fetchProfileDetails(isToken)),
        updateLocationSwitch: (value) => dispatch(updateLocationStatus(value)),
        updateIsEdit: (value) => dispatch(updateIsEdit(value)),
        storeRegistrationFlagInAsync: () => dispatch(storeRegistrationFlagInAsync()),
        isDeviceConnected: (value) => dispatch(isDeviceConnected(value)),
        requestLocationPermissions: () => dispatch(requestLocationPermissions()),
        passwordChanged: (value) => dispatch(updateIsPasswordChanged(value)),
        isEditPage: (value) => dispatch(isEditPage(value)),
        getDeviceName: () => dispatch(getDeviceName()),
        shouldEnableLocation: (value) => dispatch(shouldEnableLocation(value)),
        fetchLocationList: () => dispatch(fetchLocations()),
        syncRecords: (url,userName,password,locationList,deviceId,isFromError,shouldPresentErrorMsg) => dispatch(syncFailedRecords(url,userName,password,locationList,deviceId,isFromError,shouldPresentErrorMsg)),
        fetchFailedRecords: (shouldShowLoader) => dispatch(fetchFailedRecords(shouldShowLoader)),
        updateDeviceAction: (action,deviceId,url) =>  dispatch(performDeviceAction(action,deviceId,url)),
        callLogoutApi: (userName,password) => dispatch(callLogoutApi(userName,password)),
        syncDeviceActions: () => dispatch(syncDeviceActions()),
        syncPendingUpdates: (url,userName,password,deviceId) => dispatch(syncPendingUpdates(url,userName,password,deviceId)),
        fetchPendingLocationsList: () => dispatch(fetchPendingLocationsList()),
        showPasswordChangeAlert: (alertFlag,navigation) => dispatch(handleUIForPasswordChange(alertFlag,navigation)),
    }
}

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

以下是减速器:

const initialState = {
url: '',
userName : '',
password : '',
deviceName : '',
resourceCode : '',
isDeviceConnected : false,
allFieldsFilled: false,
token: '',
gpsTrackingInterval : 5,
apiPostingInterval : 30,
failureMessage : '',
registered : false,
edited: false,
editPage: false,
isConnected: true,
shouldEnableLocation: false,
resourceDesc: '',
adminEmail: '',
companyName: ''
}

const profileReducer = (state=initialState,action) => {
    switch (action.type) {
        case actionTypes.UPDATE_URL :
        return {
            ...state,
            url: action.payload
        }
        ...
}

这是Redux动作:

export const updateURL = (url) => {
  return {
    type: actionTypes.UPDATE_URL,
    payload: url
  };
};

任何帮助将不胜感激。

import React, { Component } from 'react';
import {
  StyleSheet, Text, View, TextInput, TouchableOpacity, Image,
  KeyboardAvoidingView, ScrollView, SafeAreaView, Linking
} from 'react-native';
import { COLOR_BLACK, COLOR_GRAY_9, COLOR_TRANSPARENT, COLOR_GRAY_4 } from '../../../constants/colors';
import ImgProntoLogo from '../../../assets/images/pronto-logo.png';
import ImgPasswordVisibleIcon from '../../../assets/images/visibility.png';
import ImgUrl from '../../../assets/images/url.png';
import ImgBarcode from '../../../assets/images/scan-barcode.png';
import ImgUsernameIcon from '../../../assets/images/username.png';
import ImgPasswordIcon from '../../../assets/images/password.png';
import ImgPasswordHide from '../../../assets/images/password-hide.png';
import GlobalStyleSheet from '../../../constants/styles';
import {
  PASSWORD, USERNAME, URL_CONNECT
} from '../../../constants/strings';
import { StackActions, NavigationActions } from 'react-navigation';
import Sync from '../../../utils/Syncing';
import { AsyncStorage } from 'react-native';

export default class Configuration extends Component {
  constructor(props) {
    super(props)
    this.handleOpenURL = this.handleOpenURL.bind(this);
    this.handleScanPress = this.handleScanPress.bind(this);
  }

  async componentWillMount() {
    this.props.clearConfiguration();
    this.props.checkConnectivity();
    Linking.addEventListener('url', this.handleOpenURL);
    Sync.removeDataFromUserTable();
    Sync.removeDataFromCompanyTable();
  }

  componentDidMount() {
    console.log("COMPONENT MOUNTING");
    Linking.getInitialURL().then((url) => {
      if (url) {
        url = url.substring(18);
        this.props.updateURL(url);
      }
    }).catch(err => console.error('An error occurred', err))
  }

  componentWillReceiveProps(props) {
    console.log("WILL RECEIVE")
  }
  handleOpenURL = (event) => {
    this.props.updateURL(event.url.substring(18))
  }

  copyRights() {
    var currentYear = new Date().getFullYear().toString();
    return '© '.concat(currentYear).concat(' Pronto Software Limited.All Rights Reserved.');
  }

  // Connect the device to the pronto connect
  async connectDevice() {
    this.props.showLoader();
    this.props.resetConnectPasswordVisibility();
    await this.props.connectDevice(this.props.configuration.url,
      this.props.configuration.username, this.props.configuration.password);
    let isDeviceConnected = await AsyncStorage.getItem("isConnected");
    if (isDeviceConnected === "true") {
      const resetAction = StackActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({ routeName: 'Register' })],
      });
      this.props.navigation.dispatch(resetAction);
    }
    this.props.hideLoader();
  }

  static navigationOptions = {
    header: null
  }

  handleScanPress() {
    const action = StackActions.reset({
      index: 0,
      actions: [NavigationActions.navigate({ routeName: 'Scanner' })],
    });
    this.props.navigation.push('Scanner');
  }

  render() {
    return (
      <SafeAreaView style={GlobalStyleSheet.container}>
        <KeyboardAvoidingView style={GlobalStyleSheet.container} >
          <View style={styles.headerLogoView}>
            <Image source={ImgProntoLogo} style={styles.logo} />
          </View>
          <ScrollView keyboardShouldPersistTaps="handled" style={styles.scrollViewStyle}>
            <View style={{ flex: 1, height: '100%' }}>
              <View style={styles.viewContainer}>
                <Text style={[GlobalStyleSheet.textHeading4, GlobalStyleSheet.marginTop10,
                GlobalStyleSheet.marginBottom10]}>CONFIGURE DEVICE</Text>
                <View style={[GlobalStyleSheet.textInputView, GlobalStyleSheet.marginBottom10]}>
                  <Image style={GlobalStyleSheet.iconInputBar} source={ImgUrl} />
                  <TextInput
                    underlineColorAndroid={COLOR_TRANSPARENT}
                    style={GlobalStyleSheet.textInput}
                    autoCapitalize='none'
                    placeholder={URL_CONNECT}
                    value={this.props.configuration.url}
                    onChangeText={(value) => { this.props.updateURL(value) }}
                    editable={!(this.props.configuration.isDeviceConnected)} 
                    />
                    <TouchableOpacity style={[GlobalStyleSheet.passwordTouchable]} onPress={this.handleScanPress}>
                      <Image style={[GlobalStyleSheet.passwordShowHideIcon]} source={ImgBarcode} />
                    </TouchableOpacity>
                </View>
                <View style={[GlobalStyleSheet.textInputView, GlobalStyleSheet.marginBottom10]}>
                  <Image style={GlobalStyleSheet.iconInputBar} source={ImgUsernameIcon} />
                  <View style={[GlobalStyleSheet.flexRow, { flex: 1 }]}>
                    <TextInput
                      placeholder={USERNAME}
                      underlineColorAndroid={COLOR_TRANSPARENT}
                      style={GlobalStyleSheet.textInput}
                      onChangeText={(value) => { this.props.updateUsername(value) }}
                      editable={!(this.props.configuration.isDeviceConnected)} 
                      />
                  </View>
                </View>
                <View style={[GlobalStyleSheet.textInputView, GlobalStyleSheet.marginBottom10]} >
                  <Image style={[GlobalStyleSheet.iconInputBar]} source={ImgPasswordIcon} />
                  <View style={[GlobalStyleSheet.flexRow, { flex: 1 }]}>
                    <TextInput
                      placeholder={PASSWORD}
                      underlineColorAndroid={COLOR_TRANSPARENT}
                      contextMenuHidden={true}
                      style={GlobalStyleSheet.textInput}
                      autoCapitalize='none'
                      onChangeText={(value) => { this.props.updatePassword(value) }}
                      editable={!(this.props.configuration.isDeviceConnected)}
                      secureTextEntry={!(this.props.configuration.passwordVisibility)} />
                    <TouchableOpacity style={[GlobalStyleSheet.passwordTouchable]}
                      onPress={() => {
                        if (!this.props.configuration.isDeviceConnected) {
                          this.props.togglePasswordVisibility(this.props.configuration.passwordVisibility)
                        }
                      }}>
                      {
                        this.props.configuration.passwordVisibility ?
                          (<Image style={[GlobalStyleSheet.passwordShowHideIcon]} source={ImgPasswordVisibleIcon} />) :
                          (<Image style={[GlobalStyleSheet.passwordShowHideIcon]} source={ImgPasswordHide} />)
                      }
                    </TouchableOpacity>
                  </View>
                </View>
                {
                  this.props.configuration.isDeviceConnected ?
                    (
                      <TouchableOpacity style={GlobalStyleSheet.touchableBarProcessed} disabled={true} >
                        <Text style={GlobalStyleSheet.textTouchableBarProcessed}>CONNECTED</Text>
                      </TouchableOpacity>
                    ) :
                    (this.props.configuration.url != "" &&
                      this.props.configuration.username != "" && this.props.configuration.password != "" ?
                      (
                        <TouchableOpacity style={[GlobalStyleSheet.touchableBarEnabled]}
                          onPress={async () => { await this.connectDevice() }}>
                          <Text style={GlobalStyleSheet.textTouchableBarEnabled}>CONNECT</Text>
                        </TouchableOpacity>
                      ) :
                      (
                        <TouchableOpacity style={[GlobalStyleSheet.touchableBarDisabled]} disabled={true}>
                          <Text style={[GlobalStyleSheet.textTouchableBarDisabled]}>CONNECT</Text>
                        </TouchableOpacity>
                      )
                    )
                }
              </View>
            </View>
            <View style={styles.copyRightsView}>
              <Text style={GlobalStyleSheet.copyRightsText}>{this.copyRights()}</Text>
            </View>
          </ScrollView>
        </KeyboardAvoidingView >
      </SafeAreaView >
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    height: '100%',
    width: '100%',
    backgroundColor: COLOR_GRAY_9,
  },
  headerLogoView: {
    height: 50,
    backgroundColor: COLOR_GRAY_9,
    elevation: 5,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: 2,
    shadowOffset: { width: 2, height: 2, },
    shadowColor: COLOR_BLACK,
    shadowOpacity: 0.1,
  },
  logo: {
    height: 40,
    width: '80%',
    resizeMode: 'contain',
  },
  viewContainer: {
    marginLeft: 15,
    marginRight: 15,
    paddingBottom: 10
  },
  copyRightsView: {
    alignItems: 'center',
    minHeight: 40,
    paddingBottom: 5,
  },
  scrollViewStyle: {
    flex: 1,
    height: '100%',
    paddingTop: 10
  },
});

0 个答案:

没有答案