ReactJS | Компонент для получения реквизитов в виде постоянных или серверных значений с обещаниями
Я сделал небольшой компонент многократного использования Formik
, Это довольно просто. Пример библиотеки послужит хорошей отправной точкой, поэтому я поделюсь им ниже, а также URL
:
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"));
Я передаю вместо жестко закодированных значений реквизит флажка, который имеет строки PropTypes
). Этот реквизит-заполнитель затем заполняется значениями, которые я передаю в зависимости от использования из Constants.js
файл вроде так.
const NameForCheckbox = {
Name1: 'Value1',
Name2: 'Value2',
Name3: 'Value3',
};
export default NameForCheckbox; // Tha is working just fine.
Проблема: в будущем мы можем получить эту информацию от Server Payload
, Это сделает мой подход устаревшим, поэтому, чтобы проверить его в будущем, я хочу, чтобы он отображал либо мои данные, если нет данных на сервере, либо обходил их, если есть значения сервера.
Теперь я читал о том, как это сделать, и обнаружил, что Promises способен решить мою проблему. Я пробовал разные вещи, которые не буду перечислять здесь, как я выяснил из других ответов в Stack Overflow, чтобы они не были правильными. Буду признателен, если вы поможете мне здесь.
МОЯ НАСТРОЙКА: До сих пор я делал это, что могло быть совершенно неприменимо, но я перечислю это.
Я создаю 3 действия, используя приставку (GetDataAttempt, GetDataSucces, GetDatFailure
). Которые взамен делают 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;
Наконец, редукторы либо отправят полезную нагрузку на компонент, который я прочитал MapStateToProps
или пустая строка.
Теперь о хитрой части и причина, которую я спросил. Как заставить эту условную логику применять к компонентам, использующим Обещания. Или что-нибудь еще.
1 ответ
Я не уверен, понимаю ли я, как обещания сильно меняются здесь.
Если я вас правильно понимаю, вы хотите отобразить статический контент в 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);
}