реагировать на собственное обновление состояния редукции, но не на рендеринг - PullRequest
0 голосов
/ 05 ноября 2019

У меня есть 2 компонента с именами A и B, в BI есть список языков, которые должны быть выбраны и обновлены в компоненте A. Я использую Redux для управления состояниями, когда я меняю язык из списка, я вижу, что состоянияобновлено (используя redux-logger для получения логов). Но проблема в том, что когда я возвращаюсь к Компоненту A, используя react-navigation обновленное значение состояния не обновляется, я вижу только старое значение только состояния

ScreenA.js

class ScreenA extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      selectedLanguage: this.props.state.defaultLangName
    }
  }

  render(
       return (
            <Container>
            <Content  style={{  backgroundColor: item.backgroundColor }}>
              <View style={styles.logoContainer}>
              <Text>test page</Text>
              </View>

            <View style={styles.cardParent}>
              <View style={styles.card}>
              <Item style={styles.listItem}>
                <Button transparent style={styles.contentChecked} onPress={() => this._openLang()}>
                  <Text style={styles.listbtn}>{this.state.selectedLanguage}</Text>
                  <Icon name='ios-arrow-forward' style={styles.iconChecked}/>
                </Button>   
              </Item>
              </View>
              </View>
            </Content>
        </Container>
          );
  )

}

export default connect(
    state => ({ state : state.introauthenticate }),
    dispatch => ({
        actions: bindActionCreators(introActions, dispatch)
    })
  )(ScreenA);

ScreenB.js

class ScreenB extends Component {

    constructor(props){
      super(props);
      this.state = {
              langChecked: '0'
          };
    }


    FlatListItemSeparator = () => {
        return (
          <View
            style={{
              height: 1,
              width: "100%",
              backgroundColor: "#999",
            }}
          />
        );
    }

    _selectLanguage (val, name){
      this.setState({ langChecked: val });
      this.props.actions.changeLanguage(val,name, this.props.navigation.navigate);
      //this.props.navigation.navigate('Intro');
    }

    renderItem = (item )=> {
      return(
        <TouchableHighlight
            style={styles.boxSelect}
            underlayColor="transparent"
            onPress={() => this._selectLanguage(item.Value, item.Name)}
        >
            <View style={styles.contentChecked}>
              <Text style={styles.item}  > {item.Name} </Text>
              {this.state.langChecked === item.Value && <Icon name="ios-checkmark-circle" style={styles.iconChecked}/>}
            </View>
         </TouchableHighlight>
      )
    }

    render() {
      return (
          <Container>
          <Header>
            <Left>
              <Button transparent onPress={() => this.props.navigation.goBack()}>
                <Icon name='ios-arrow-back' />
              </Button>
            </Left>
            <Body>
              <Title>Languages</Title>
            </Body>
            <Right />
          </Header>        
        <Content>
        <FlatList
         data={ langs }
         keyExtractor={(item) => item.Value}
         ItemSeparatorComponent = {this.FlatListItemSeparator}
         renderItem={({item}) => this.renderItem(item)}
        />
        </Content>
      </Container>
      );
    }
  }

  export default connect(
    state => ({ state: state.introauthenticate }),
    dispatch => ({
        actions: bindActionCreators(introActions, dispatch)
    })
  )(ScreenB);

reducer.js

export const CHANGE_LANGUAGE = "CHANGE_LANGUAGE";

export function changeLanguage(langValue,langName,navigateTo) { // Fake authentication function
  return async dispatch => {
      try {
          if (langValue && langName) { //If the email and password matches
              const session = { langValue : langValue,langName:langName } // Create a fake token for authentication

              setTimeout(() => { // Add a delay for faking a asynchronous request
                  dispatch(setLanguage(session)) // Dispatch a successful sign in after 1.5 seconds
                  navigateTo('Intro') // If successfull login navigate to the authenticated screen
              }, 1500)
          }  
      } catch (err) { // When something goes wrong
          console.log(err)

      }
  };
} 


function setLanguage(lang){
  return {
      type: types.CHANGE_LANGUAGE,
      data: {
          lang: lang
      }
  };
}

const initialsliderState = {
    defaultLang:'en',
    defaultLangName:'English',
  };

  export default function introauthenticate(state = initialsliderState, action = {}) {

    switch (action.type) {
        case types.CHANGE_LANGUAGE: 
        return { 
          ...state,
          defaultLang: action.data.lang.langValue,
          defaultLangName: action.data.lang.langName,
        };
      default:
        return state;
    }
  }

Регистратор:

LOG  %c prev state  "introauthenticate": {"defaultLang": "nl", "defaultLangName": "Deutsch", "isAuthSlider": false, "requestingsliderRestore": false}
LOG  %c action      {"data": {"lang": {"langName": "English", "langValue": "en"}}, "type": "CHANGE_LANGUAGE"}
LOG  %c next state "introauthenticate": {"defaultLang": "en", "defaultLangName": "English", "isAuthSlider": false, "requestingsliderRestore": false}}

1 Ответ

1 голос
/ 05 ноября 2019

Вы инициализируете состояние ScreenA значением, переданным как реквизит, и никогда не обновляете его. Поскольку вы используете redux для хранения текущего языка, вам не нужно никакого состояния в ScreenA. При подключении компонента вы передаете ему соответствующие данные из вашего магазина в качестве реквизита. Похоже, вы пытаетесь «переопределить» состояние, передавая его как state, но это не обновляет состояние, поскольку оно будет в this.props.state, а не в this.state. Что вам нужно сделать, это просто передать язык как реквизит ScreenA:

export default connect(
    state => ({ selectedLanguage : state.introauthenticate.defaultLang }),
    dispatch => ({
        actions: bindActionCreators(introActions, dispatch)
    })
)(ScreenA);

, а затем прочитать выбранный язык из реквизита:

<Text style={styles.listbtn}>{this.props.selectedLanguage}</Text>

Когда вы обновляете свойсохранить компонент будет повторно визуализировать с новым языком. Вам не нужно никакого дополнительного состояния в самом компоненте для данных, которые у вас есть в вашем хранилище приставок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...