Как использовать Redux и React навигацию для создания глобального счетчика - PullRequest
0 голосов
/ 02 апреля 2020

Я делаю приложение React-Native, в котором у меня есть навигатор от React Navigation, и я также хочу реализовать Redux. Я пытаюсь создать глобальный счетчик, который обновляется на основе аргумента. Вот действия:

export const setFlags = (value) => {
return {
    type: 'SETFLAGS',
    value
}

}

export const setNonFlags = (value) => {
    return {
        type: 'SETNONFLAGS',
        value
    }
}

Вот редуктор, потому что его две вещи, которые имеют одинаковую функциональность, я думал, что одна будет работать (я новичок в Redux):

   const initialState = {
    flags:0,
    nonFlags:0,

}

const AllFlagReducer = (state = initialState, action) =>{
    switch(action.type){


        case 'SETFLAGS':
            return state.flags = state.flags + action.value
        case 'SETNONFLAGS':
            return state.nonFlags = state.nonFlags + action.value

    }
    return state
}

export default AllFlagReducer

А вот кнопка, на которой я хотел бы отправить локальное состояние "flag" и "nonFlag" в глобальные состояния Redux. После чего я сбрасываю локальные состояния и перехожу на следующий экран.

<TouchableOpacity style={styles.resetButton}
            onPress= {
              // dispatch something like flags(in redux):this.state.flags
              // dispatch nonFlags(in redux): this.state.nonFlags
              () =>{this.resetAll();
              navigation.navigate('Specific Scams')

            }}>

Помощь будет принята с благодарностью. ОБНОВЛЕНИЕ 1: Весь компонент:

class ScamTree extends React.Component {
constructor(props){
  super(props)
  this.state = {
    flags : 0,
    nonFlags: 0,
    qAnswered:0
  }
}

функции, которые могут иметь значение:

resetAll = () =>{
  this.setState({flags:0})
  this.setState({nonFlags:0})
  this.setState({qAnswered:0})

}

кнопка, (я не сделал отдельный компонент только для кнопки):

<TouchableOpacity style={styles.resetButton}
            onPress= {
              // dispatch something like flags:this.state.flags
              // dispatch nonFlags: this.state.nonFlags
              () =>{this.resetAll();store.dispatch({type:"SETFLAGS",value:5})
              navigation.navigate('Specific Scams')

            }}>

            <Text style={{paddingHorizontal:40}}>NEXT</Text>
          </TouchableOpacity>

экспорт для работы React Navigation:

export default function(props) {
const navigation = useNavigation();

return <ScamTree {...props} navigation={navigation} />;

}

Ответы [ 3 ]

2 голосов
/ 02 апреля 2020

В вашем классе. js вы должны связать свое действие следующим образом

  import { bindActionCreators } from 'redux'
  import { connect } from 'react-redux';

  <TouchableOpacity style={styles.resetButton}
        onPress= {
          // dispatch something like flags(in redux):this.state.flags
          // dispatch nonFlags(in redux): this.state.nonFlags
          () =>{
          this.resetAll();
          this.props.commanAction.setFlags(your value);
          this.props.commanAction.setNonFlags(your value);
          navigation.navigate('Specific Scams')

        }}>

  const mapDispatchToProps = dispatch => {
      return {
         commanAction: bindActionCreators(commanAction, dispatch)
      };
   };

  export default connect(mapStateToProps, mapDispatchToProps)(Your .js className);

Другой код выглядит хорошо.

0 голосов
/ 02 апреля 2020

Если я понимаю ваш комментарий в другом ответе и фрагмент обновления вашего вопроса, я считаю, что вам нужно украсить этот функциональный компонент:

export default function(props) {
  const navigation = useNavigation();

  return <ScamTree {...props} navigation={navigation} />;
}

Вы хотите Украсьте этот компонент connect HO C, чтобы подключить его к вашему хранилищу редуксов.

Сначала я бы преобразовал эту функцию в новый withNavigation HO C:

const withNavigation = WrappedComponent => props => {
  const navigation = useNavigation();
  return <WrappedComponent{...props} navigation={navigation} />;
};
withNavigation.displayName = `withNavigation(${WrappedComponent.displayName || 'Component'})`;

Теперь вы можете украсить ScamTree следующим образом:

export default withNavigation(ScamTree);

Но теперь вам также нужно подключить создателей ваших действий к вашему магазину излишков, украсив его react-redux ' s connect HO C:

const mapDispatchToProps = {
  setFlags,
  setNonFlags,
};

export default withNavigation(
  connect(null, mapDispatchToProps)(ScamTree),
);

Примечание: я вижу, что вы храните в локальном состоянии некоторые значения флага, не уверен, что это связано, но вы можете отобразить для этого начальное состояние с mapStateToProps в качестве первого параметра для подключения вместо NULL.

К настоящему времени вы, вероятно, заметили, что каждый новый HO C создает некоторое вложение , и это будет ухудшаться с увеличением количества используемых HO C. Решение состоит в том, чтобы использовать redux compose HO C. Это верно, это не только для создания промежуточного программного обеспечения для магазина. Он может объединить все декораторы в один HO C, чтобы обернуть экспортируемый компонент, или, другими словами, он выравнивает / исключает вложение.

Советы

Все, что делает compose, позволяет вам писать глубоко вложенные преобразования функций без смещения кода вправо. Не придавайте этому особого значения!

...
import { compose } from 'redux';
...

class ScamTree extends Component { ... }

const mapDispatchToProps = {
  setFlags,
  setNonFlags,
};

export default compose(
  withNavigation,
  connect(null, mapDispatchToProps),
)(ScamTree);

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

const AllFlagReducer = (state = initialState, action) => {
  switch(action.type){
    case 'SETFLAGS':
        return { ...state, flags: state.flags + action.value };

    case 'SETNONFLAGS':
        return { ...state, nonFlags: state.nonFlags + action.value };

    default:
      return state;
  }
}
0 голосов
/ 02 апреля 2020

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


const AllFlagReducer = (state = initialState, action) =>{
 switch(action.type){
    case 'SETFLAGS':
        return { ...state, flags: state.flags + action.value }
    case 'SETNONFLAGS':
        return { ...state, nonFlags: state.nonFlags + action.value }
    default: return state
     }
    }
export default AllFlagReducer

...