反应-您可以从外部函数更新未声明的容器状态吗?

时间:2018-09-11 22:25:17

标签: reactjs react-context unstated

在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 :(得分:3)

该问题并非仅针对Unstated,这也适用于使用渲染属性模式的React上下文API。

login的问题在于其控制流程有缺陷。它无法抑制错误,因此无法有效捕获错误。并将promise封装在内部,这是一个错误,阻止了对初学者的正确测试

它可以暴露一个承诺,或者接受一个回调,或者两者都可以:

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作为参数,但这会将其耦合到不必要的实现上。

答案 1 :(得分:1)

这是一个常见问题,有许多解决方案。您需要将该函数传递给子级,然后再更新父级。我将链接到我之前发布的答案。就您而言,在哪里渲染

<Login upParentCounter={this.increment}/>

在登录组件内部

this.props.upParentCounter()

Dealing with Nested React Components' State Changes