перекомпоновать withHandlers асинхронно?

Возможно/безопасно ли использовать withHandlers с промисами? Бывший.:

withHandlers({
    onChange: props => event => {
      props.callAPI(props.data)
        .then(data => props.updateData(data))
    },
...

Спасибо!


person DavidC    schedule 17.01.2017    source источник


Ответы (2)


После некоторых тестов я понял, что это работает довольно хорошо. Перекомпонуйте камни для строительства из чистых компонентов.

Это совершенно верно и работает очень хорошо.

const enhWithHandlers = withHandlers({
  loginUserMutation: props => args => {
    props.updateMutationState(loading: true, error: null });
    props.loginUser(args)
      .then(() =>
        props.updateMutationState({loading: false, error: null }))
      .catch(err =>
        props.updateMutationState({ loading: false, error: err }));
  }
},
...
// then compose like
export default compose(
  reduxConnect,
  gqlConnectLogin,
  gqlConnectRegister,
  enhWithState,
  enhWithHandlers
)(UserLoginRegister);

Это помогает мне преодолеть отсутствие возможности отражать результаты мутации graphQl с клиентом Apollo в завернутый составная часть. Это отлично справляется с этим и не требует побочных эффектов в самом компоненте.

person DavidC    schedule 17.01.2017
comment
Да, это безопасно и возможно - person wuct; 19.01.2017

Но есть некоторые проблемы, когда мы используем его следующим образом:

compose(
  withState('loginStatus', 'setLoginStatus', {loading: false, error:null}),
  withHandlers({
    loginUserMutation: props => async args => {
      try {
        props.setLoginStatus({loading: true, error: null});
        await props.loginUser(args);
      } catch(error) {
        props.setLoginStatus({...props.loginStatus, error});
      } finally {
        props.setLoginStatus({...props.loginStatus, loading: false});
      }
    }
  })
)

Поскольку ссылка props действительно теряется после того, как мы await props.loginUser(args). Затем мы используем его после того, как это неправильно.

Обратите внимание, что его нельзя использовать, как указано выше.


person xialvjun    schedule 21.07.2017
comment
Я не понимаю, что ссылка props потеряна. Это не так, и вы даже не используете его. Может быть, вы имеете в виду, что finally не запускается. Это имеет смысл, если loginUser(args) изменяет состояние приложения, поэтому обернутый компонент размонтируется. Или можно чуть подробнее? Мы широко используем recompose, и у нас нет абсолютно никаких проблем с этим. - person DavidC; 27.07.2017
comment
Я имею в виду, что аргумент props равен this.props, но после того, как вы setLoginStatus and await loginUser (setLoginStatus похож на this.setState), аргумент props уже не равен this.props.... Это как: const props = this.props; this.setState({xxx}); api().then(_ => console.log(props == this.props)); будет логироваться false... - person xialvjun; 31.07.2017
comment
Я бы порекомендовал не думать о recompose как о компоненте с состоянием (и вообще не думать о this. Ваш await props.loginUser(args); изменит реквизиты в более высоком компоненте, и это вызовет пересчет дерева компонентов. Вот почему после этого await реквизиты могут быть отличается, если loginUser изменяет реквизиты на более высоком уровне компонента (но только если вы передаете эту информацию вниз).И поэтому обычно, если вы используете, например, ветку (чтобы решить, отображать ли логин или данные пользователя), после loginUser ваш компонент будет размонтируется, и все, что после этого, станет неработоспособным. - person DavidC; 01.08.2017