Реагировать - Можете ли вы обновить состояние Unstated контейнера из внешней функции? - PullRequest
0 голосов
/ 12 сентября 2018

В примере из библиотеки Unstated они обновляют состояние в контейнере, взаимодействуя с кнопкой jsx, которая подписана на контейнер.

import React from 'react';
import { render } from 'react-dom';
import { Provider, Subscribe, Container } from 'unstated';

type CounterState = {
  count: number
};

class CounterContainer extends Container<CounterState> {
  state = {
    count: 0
  };

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  decrement() {
    this.setState({ count: this.state.count - 1 });
  }
}

function Counter() {
  return (
    <Subscribe to={[CounterContainer]}>
      {counter => (
        <div>
          <button onClick={() => counter.decrement()}>-</button>
          <span>{counter.state.count}</span>
          <button onClick={() => counter.increment()}>+</button>
        </div>
      )}
    </Subscribe>
  );
}

render(
  <Provider>
    <Counter />
  </Provider>,
  document.getElementById('root')
);

Есть ли способ обновить состояние в контейнере сфункция в компоненте вне контейнера?Например, если я хочу обновить состояние при возврате обещания, как бы я поступил так?Псевдокод

login = () => {
    let url = baseURL + '/user/login?_format=json';  

    let data = {
      "name": this.state.email,  
      "pass": this.state.password
    };



        axios({
          url,
          method: "POST",
          headers: {
            'Accept':  'application/json',
            'Content-Type': 'application/json',
          },
          withCredentials: true,
          credentials: 'same-origin', 
          data,
          })
          .then(function(result) {
            console.log('result:', result);
                SET STATE HERE!!!!!!!
counter.increment()

              })
          .catch(error => console.log('error:', error));
      };

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Проблема не относится к Unstated, это относится и к контекстному API React, в котором также используется шаблон рендеринга.

Проблема с login заключается в том, что его поток управления имеет недостатки. Он не сможет эффективно отлавливать ошибки, потому что он их подавляет. И оно заключает в себе обещание внутри, что является ошибкой, которая мешает его должным образом проверить, для начала

Может выставлять обещание или принимать обратный вызов, или оба:

login = async (cb) => {
  ...    
  return axios(...)
  .then(function(result) {
    if (cb)
      cb(result);

    return result;
  })
  .catch(error => console.log('error:', error));
}

Может использоваться как:

<button onClick={() => login(() => counter.decrement())}>-</button>

Или:

<button onClick={async () => { await login(); counter.decrement(); }}>-</button>

Также можно сделать login принять counter в качестве аргумента, но это связало бы его с реализацией, которая не нужна.

0 голосов
/ 12 сентября 2018

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

<Login upParentCounter={this.increment}/>

И внутри компонента входа в систему

this.props.upParentCounter()

Работа с изменениями состояния вложенных компонентов реакции

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