首页 > 解决方案 > 反应JS | 使用 Promises 以常量或服务器值的形式接收 props 的组件

问题描述

我使用Formik. 这是非常基本的。图书馆的例子是一个很好的起点,所以我在下面分享它以及URL

Formik 示例的代码沙箱

import React from "react";
import { render } from "react-dom";
import { Formik, Field } from "formik";

function Checkbox(props) {
  return (
    <Field name={props.name}>
      {({ field, form }) => (
        <label>
          <input
            type="checkbox"
            {...props}
            checked={field.value.includes(props.value)}
            onChange={() => {
              if (field.value.includes(props.value)) {
                const nextValue = field.value.filter(
                  value => value !== props.value
                );
                form.setFieldValue(props.name, nextValue);
              } else {
                const nextValue = field.value.concat(props.value);
                form.setFieldValue(props.name, nextValue);
              }
            }}
          />
          {props.value}
        </label>
      )}
    </Field>
  );
}

function App() {
  return (
    <Formik
      initialValues={{
        roles: ["admin"]
      }}
      onSubmit={values => alert(JSON.stringify(values, null, 2))}
    >
      {formik => (
        <div>
          <div>
            <Checkbox name="roles" value="admin" />
            <Checkbox name="roles" value="customer" />
          </div>
          <button onClick={formik.submitForm}>submit</button>
          <pre>{JSON.stringify(formik.values, null, 2)}</pre>
        </div>
      )}
    </Formik>
  );
}

render(<App />, document.getElementById("root"));

我传递的不是硬编码的值,而是 Checkbox 的道具,它具有字符串 (Using PropTypes) 的属性。这个占位符道具然后由我传递的值填充,具体取决于Constants.js像这样的文件的使用情况。

const NameForCheckbox = {
  Name1: 'Value1',
  Name2: 'Value2',
  Name3: 'Value3',
};

export default NameForCheckbox; // Tha is working just fine.

问题: 我们将来可能会从Server Payload. 这将使我的方法过时,因此为了将来证明它,如果不存在服务器数据,我想让它呈现我的数据,或者如果有服务器值则绕过它们。

现在,我正在阅读如何做到这一点,我发现 Promises 能够解决我的问题。我尝试了各种我不会在这里列出的东西,因为我发现 Stack Overflow 中的其他答案不正确。如果你能在这里帮助我,我将不胜感激。

我的设置:到目前为止,我这样做了,这可能完全不可用,但我会列出它。

我使用 redux( GetDataAttempt, GetDataSucces, GetDatFailure) 创建了 3 个动作。作为回报GET,它会向该特定端点发出请求。反过来,这将使用一些像这样的 RxJS 函数

import { of } from 'rxjs';
import { switchMap, map, catchError } from 'rxjs/operators';

import { observableFromHttpPromise, combineAndIsolateEpics } from 'utilities/epicsUtil';
import { Type, Actions } from '../actions';

const getDataEpic = (action$, store, deps) =>
  action$.ofType(Type.GET_DATA_ATTEMPT).pipe(
    switchMap(() =>
      observableFromHttpPromise(deps.getData()).pipe(
        map(result => Actions.getDataSuccess(result && result.data)),
        catchError(error => of(Actions.getDataFailure(error && error.message)))
      )
    )
  );

const getAllEpics = combineAndIsolateEpics(getDataEpic);

export default getAllEpics;

最后,reducers 会将有效负载发送到我使用的组件MapStateToProps或空字符串。

现在到棘手的部分和我问的原因。如何使用 Promises 将此条件逻辑应用于组件或者别的什么。

标签: reactjsreduxrxjses6-promiseformik

解决方案


我不确定我是否理解这里的承诺如何变化。

如果我对您的理解正确,您希望在其中显示静态内容,NameForCheckbox除非存在某些服务器信息。显然,获取这些信息是异步的。

最简单的可能实现是在组件挂载时分派您的 API 请求(可能通过操作)。同时,您可以NameForCheckbox使用一些简单的条件逻辑来显示值,以显示 API 数据(如果存在)或复选框。

import NameForCheckbox from './NameForCheckbox';

class Checkboxes extends React.Component {

  componentDidMount = () => {
    // dispatch async action here that will eventually populate the
    // apiData prop below
  }

  renderCheckboxes = data => {
    // insert rendering logic here
  }

  render() {
    const { apiData } = this.props;
    const data = someData || NameForCheckbox;

    return this.renderCheckboxes(data);
  }
}

const mapStateToProps = state => ({
  apiData: state.reducer.data || null;
})

data请注意,当 apiData 为假时(两者null或,正如您所建议的那样)是如何落入默认数据''的,但是当来自 API 的数据以状态存在时,它将改为呈现该数据。

在等待数据返回时设置加载动画也很常见,因此您也可以从初始状态 开始loading = true,然后loading = false在 API 操作成功完成时设置。

// In reducer
const initialState = {
  loading: true,
  apiData: null
}

// In component
render() {
  const { apiData, loading } = this.props;

  if (loading) return <Loading />;

  return this.renderCheckboxes(apiData);
}

推荐阅读