Redux-thunk调度一个动作并等待重新渲染

Ave*_*235 12 javascript reactjs redux redux-thunk

import React from "react";
import { render } from "react-dom";
import { createStore, applyMiddleware } from "redux";
import { Provider, connect } from "react-redux";
import thunk from "redux-thunk";

const disabled = (state = true, action) => {
  return action.type === "TOGGLE" ? !state : state;
};

class Button extends React.Component {
  componentDidUpdate(prevProps) {
    if (prevProps.disabled !== this.props.disabled && !this.props.disabled) {
      //  this.ref.focus();  // uncomment this to see the desired effect
    }
  }
  render() {
    const { props } = this;
    console.log("rendering", props.value);
    return (
      <div>
        <input
          type="checkbox"
          onClick={() => {
            props.toggle();
            this.ref.focus(); // doesn't work
          }}
        />
        <input
          disabled={props.disabled}
          ref={ref => {
            this.ref = ref;
          }}
        />
      </div>
    );
  }
}

const toggle = () => ({
  type: "TOGGLE"
});

const A = connect(state => ({ disabled: state }), { toggle })(Button);

const App = () => (
  <Provider store={createStore(disabled, applyMiddleware(thunk))}>
    <A />
  </Provider>
);

render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)

编辑redux-thunk-promise

我想input在选中复选框时关注.但是,this.ref.focus()必须在组件重新渲染之后调用props.disabled === false,因为inputdisabledprop无法集中.

如果我做逻辑componentDidUpdate,我就能实现我想要的.但这不是一个干净的解决方案,因为逻辑特定于onClick处理程序而不是生命周期事件.

有没有其他方法可以实现这一目标?(最好使用工作代码框示例)

Ree*_*kle 1

我认为您可以确信state在执行focus()调用之前更新的 Redux 数据就在那里,因为数据流如下:

  1. 调度异步操作toggleThunk,并等待其解决
  2. then调度同步操作来更新state(新state数据),并等待其解决(?)
  3. then focus()您的文献

https://codesandbox.io/s/r57v8r39om

编辑 redux-thunk-promise

请注意,在您的 OP 中,您的toggle()动作创建者不是 thunk。另外,强制您的 thunk 返回 Promise 是一个很好的规则,以便您可以按照您所描述的方式控制数据流。

import React from "react";
import { render } from "react-dom";
import { createStore, applyMiddleware } from "redux";
import { Provider, connect } from "react-redux";
import thunk from "redux-thunk";

const disabled = (state = true, action) => {
  return action.type === "TOGGLE" ? !state : state;
};

class Button extends React.Component {
  textInput = React.createRef();

  handleClick = () => {
    const { toggleThunk } = this.props;
    toggleThunk().then(() => {
      this.textInput.current.focus();
    });
  };

  render() {
    const { disabled, value } = this.props;
    return (
      <div>
        <input type="checkbox" onClick={this.handleClick} />
        <input disabled={disabled} ref={this.textInput} />
      </div>
    );
  }
}

// Action
const toggle = () => ({
  type: "TOGGLE"
});

// Thunk
const toggleThunk = () => dispatch => {
  // Do your async call().then...
  return Promise.resolve().then(() => dispatch(toggle()));
};

const A = connect(state => ({ disabled: state }), { toggleThunk })(Button);

const App = () => (
  <Provider store={createStore(disabled, applyMiddleware(thunk))}>
    <A />
  </Provider>
);

render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)