React Native + Redux: почему из магазина извлекается старое состояние? - PullRequest
0 голосов
/ 07 марта 2020

Я застрял на этом в течение последних нескольких дней и понятия не имею, что я делаю неправильно. Для целей этого вопроса я создал простой калькулятор, который умножает число от пользователя на 2.

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

initialState = {number: '', result: ''}

const calculatorReducer = (state = initialState, action) => {
  switch (action.type) {
    case CHANGE_VALUE:
      return {
        ...state,
        [action.field]: action.value
      };
  }

  return state

}

Кстати, мы можем получить значение просто с помощью этой функции:

export const getValue = (state, field) => {
    return state[field];
}

И у нас есть следующие два компонента , Родитель отвечает за логи c:

const CalculatorLogic = props => {
  const evaluate = () => {
      props.changeValue('result', props.getValue('number') * 2)
  }

  return (
    <View style={styles.container}>
        <MyInput name="number" onChange={evaluate}/>
        <MyInput name="result" onChange={evaluate}/>
    </View>
  );
}

function mapStateToProps(state) {
    return {
        getValue: (field) => getValue(state, field),
    }
}

function mapDispatchToProps(dispatch) {
    return {
        changeValue: (field, value) => dispatch(changeValue(field, value)),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(CalculatorLogic)

Вот поле ввода, которое мы используем:

const MyInput = props => {
    const valueHandler = value => {
        if (props.value != value) { // user changed a value?
            props.changeValue(props.name, value) // then change it in state
            props.onChange()  // and call evaluate function in parent
        }
    }

    return (
        <View style={{padding: 20}}>
            <Text>Field {props.name}</Text>
            <TextInput
                style={{width: 200, border: 1}}
                onChangeText={valueHandler}
                value={props.value ? props.value.toString() : ''}
            />
        </View>
  );
}

function mapStateToProps(state, ownProps) {
    return {
        value: getValue(state, ownProps.name),
    }
}

function mapDispatchToProps(dispatch) {
    return {
        changeValue: (field, value) => dispatch(changeValue(field, value)),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyInput)

Мой вопрос: почему он рендерит поздно?

Например:

  1. Пользователь нажимает номер 7, ничего не происходит (должно отображаться 14, что равно 7 * 2).
  2. Затем пользователь вводит 5 и показывает 14 (7 раз 2 вместо 75 раз два).
  3. Затем пользователь вводит 3, и он показывает 150 (75 раз 2 вместо 753 раза два)

Et c.

Почему он использует старое состояние вместо текущего? Что я делаю неправильно? (Да, я хочу сохранить логин в родительском компоненте)

Спасибо !!!

1 Ответ

0 голосов
/ 08 марта 2020

Установка состояния выполняется в асинхронном режиме c. Таким образом, вы никогда не узнаете, получили ли вы текущее значение или предыдущее. React / Redux выполнит изменение состояния, когда будет доступно достаточно ресурсов (например, предварительное исполнение).

Вы можете напрямую передать number и result в функции evaluate. Это гарантировало бы самое последнее значение.

Никогда не позволяйте каким-либо логам c в вашем коде зависеть от значения текущего состояния, когда есть возможность изменить его в том же (компонентном) цикле рендеринга.

Надеюсь, это поможет вам!

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