Как создать собственное оповещение с помощью Redux? (Предупреждение: невозможно обновить во время существующего перехода состояния) - PullRequest
0 голосов
/ 08 мая 2019

Я хочу вместо использования метода Alert.alert по умолчанию создать свой собственный, чтобы я мог изменить фон моего Alert, независимо от того, успешно он или нет. Для этого я использую Modal, который помещает в мой корневой компонент App.js (чтобы модальное изображение появлялось на каждом экране):

App.js

// ...
const Navigation = createAppContainer(MainNavigator);

// Render the app container component with the provider around it
class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Navigation />
        <CustomAlert /> {/* <--- here */}
      </Provider>
    );
  }
}

Я делаю это, потому что я не хочу размещать свой <CustomAlert /> компонент на каждом экране, который я использую. Если у кого-то есть другой подход, я его выберу.

CustomAlert.js

// ... (imports)

class CustomAlert extends Component {
  render() {
    const { customStyle } = this.props;
    const { title, description, enabled } = this.props;
    const { reinit } = this.props; // dispatch
    return (
      <View>
        <Modal
          animationType="none"
          transparent
          visible={enabled}
        >

          <View style={styles.fullScreen}>
            <View style={[styles.content, customStyle]}>
              <View style={{ flex: 1 }}>
                <View style={styles.title}>
                  <Text style={{ fontWeight: 'bold' }}>{title}</Text>
                </View>

                <View style={styles.desc}>
                  <Text style={{ textAlign: 'center' }}>{`${description}`}</Text>
                </View>

                <View style={styles.buttons}>
                  <TouchableOpacity
                    onPress={() => {
                      reinit();
                    }}
                    style={styles.button}
                  >
                    <Text>OK</Text>
                  </TouchableOpacity>
                </View>
              </View>
            </View>
          </View>
        </Modal>
      </View>
    );
  }
}

function mapStateToProps(state) {
  return {
    type: state.alert.type,
    title: state.alert.title,
    description: state.alert.description,
    enabled: state.alert.enabled,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    reinit: () => dispatch(reinitState()),
  };
}

export default stylesWrapper(connect(mapStateToProps, mapDispatchToProps)(CustomAlert));

Я поступаю так: В моей функции, которая отображает предупреждение, я просто изменяю свое хранилище редуксов:

helper.js

// ...
export const infoAlert = (title, msg, type = 'error') => {
  store.dispatch(setTitle(title));
  store.dispatch(setDescription(msg));
  store.dispatch(setType(type));
  store.dispatch(setEnabled(true));
};
// ...

Поведение хорошее, но у меня есть это предупреждение:

Предупреждение: невозможно обновить во время существующего перехода состояния (например, в render). Методы рендеринга должны быть чистой функцией реквизита и состояния.

Я подозреваю, что между этими двумя причинами есть одна:

  • Использование store.dispatch в качестве общей функции ничего не знает о компоненте, который вызвал его, поэтому это сообщение указывает, что оно может повторно отобразить это (что плохо)
  • infoAlert вызывается внутри функционального компонента (Redux Form), и его состояние не должно изменяться (что-то подобное)

Вот пример вызова infoAlert (внизу):

const renderField = ({
  input,
  label,
  keyboardType,
  secureTextEntry,
  autoCapitalize,
  autoCorrect,
  meta: {
    touched, error, warning, active, dirty,
  },
}) => (
  <View>
    <TextInput
      style={[styles.textInput, (active) && styles.active,
        (touched) && (((error) && styles.error)
          || ((warning) && styles.warning))]}
      {...input}
      onChangeText={input.onChange}
      onBlur={input.onBlur}
      onFocus={input.onFocus}
      value={input.value}
      keyboardType={keyboardType}
      placeholder={label}
      secureTextEntry={secureTextEntry}
      autoCapitalize={autoCapitalize}
      autoCorrect={autoCorrect}
    />
    {(touched && !active && dirty) && (((error) && infoAlert('Erreur', error))
        || ((warning) && infoAlert('Attention', warning)))}
  </View>
);

У кого-нибудь есть идеи, как убрать это предупреждение? Есть ли у кого-то другой (возможно, более простой) способ создания настраиваемого оповещения (без размещения самого компонента везде)?

Экраны enter image description here enter image description here

...