React-redux mapStateToProps значения не обновляются - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть странный сценарий, в котором внутри моих инструментов-редукторов я вижу, что состояние редукса обновлено, но это значение не отражается в компоненте, который связан с этим.

Итак, у меня есть компонент CreateEnvironment, такой как

export interface StateProps {
  environment: EnvironmentStep;
  selectProduct: SelectProductStep;
  eula: EULAStep;
  license: LicenseStep;
  infrastructure: InfrastructureStep;
  network: NetworkStep;
  certificate: CertificateStep;
  products: any;
}

export interface DispatchProps {
  onFormValuesUpdate: (key: string, value: any) => void;
}

type Props = StateProps & DispatchProps;

interface State {
  dashboard: boolean;
}

class CreateEnvironment extends Component<Props, State> {
  private page: RefObject<any>;
  constructor(props: Props) {
    super(props);
    this.state = { dashboard: false };
    this.page = React.createRef();
  }
  public render() {
    console.log("Hi"); //tslint:disable-line
    if (this.state.dashboard) {
      return <Redirect to="/dashboard" />;
    }
    const {
      environment,
      eula,
      selectProduct,
      infrastructure,
      network,
      license,
      certificate,
      onFormValuesUpdate
    } = this.props;
    return (
      <Fragment>
        <h2>Create Environment</h2>
        <div style={{ height: '100%', paddingBottom: '30px' }}>
          <WorkFlow
            orientation="vertical"
            onNext={this.onNext}
            onFinish={this.onFinish}
          >
            <WorkFlowPage pageTitle="Environment">
              <Environment
                environment={environment}
                onUpdate={onFormValuesUpdate}
                ref={this.page}
              />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="Products & Solutions">
              <SelectProduct
                ref={this.page}
                selectProduct={selectProduct}
                onUpdate={onFormValuesUpdate}
              />
            </WorkFlowPage>
            <WorkFlowPage
              pageNavTitle="EULA"
              pageTitle="End User License Agreement Details"
            >
              <Eula eula={eula} ref={this.page} onUpdate={onFormValuesUpdate} />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="License">
              <License
                license={license}
                ref={this.page}
                onUpdate={onFormValuesUpdate}
              />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="Infrastructure">
              <Infrastructure
                infrastructure={infrastructure}
                ref={this.page}
                onUpdate={onFormValuesUpdate}
              />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="Network">
              <Network
                network={network}
                ref={this.page}
                onUpdate={onFormValuesUpdate}
              />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="Certificate">
              <Certificate
                certificate={certificate}
                ref={this.page}
                onUpdate={onFormValuesUpdate}
              />
            </WorkFlowPage>
            <WorkFlowPage pageTitle="Products">I am products step</WorkFlowPage>
            <WorkFlowPage pageTitle="Summary">I am summary step</WorkFlowPage>
            <WorkFlowButton role="previous">Back</WorkFlowButton>
            <WorkFlowButton role="next">Next</WorkFlowButton>
            <WorkFlowButton role="finish">Finish</WorkFlowButton>
          </WorkFlow>
        </div>
      </Fragment>
    );
  }

  private onNext = () => {
    if (this.page.current) {
      this.page.current.handleSubmit();
    }
  }

  private onFinish = () => {
    this.setState({
      dashboard: true
    });
  }
}

export default CreateEnvironment;

Соответствующий контейнер выглядит так:

import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import {
  CreateEnvironmentAction,
  updateEnvironmentWorkflow
} from '../actions/CreateEnvironment';
import {
  CreateEnvironment,
  DispatchProps,
  StateProps
} from '../components/create-environment';
import { StoreState } from '../types';
export const mapStateToProps = ({
  createEnvironment
}: StoreState): StateProps => ({
  ...createEnvironment
});

export const mapDispatchToProps = (
  dispatch: Dispatch<CreateEnvironmentAction>
): DispatchProps => ({
  onFormValuesUpdate: (key: string, values: any) => {
    dispatch(updateEnvironmentWorkflow(key, values));
  }
});

export default connect<StateProps, DispatchProps>(
  mapStateToProps,
  mapDispatchToProps
)(CreateEnvironment);

Все компоненты внутри WorkflowPage, такие как Environment, являются формами, использующими шаблон Formik. Пример компонента:

interface Props {
  certificate?: CertificateStep;
  onUpdate?: (key: string, value: any) => void;
}
class Certificate extends Component<Props> {
  private submitForm: (
    e?: React.FormEvent<HTMLFormElement> | undefined
  ) => void;
  public render() {
    const { formValues } = this.props.certificate!;
    console.log(formValues); //tslint:disable-line
    return (
      <Form
        className="license"
        type="horizontal"
        initialValues={formValues}
        onSubmit={this.onSubmit}
      >
        {formProps => {
          this.submitForm = formProps.handleSubmit;
          return (
            <Fragment>
              <CheckboxField
                name="productSpecific"
                id="productSpecific"
                type="toggle"
              >
                Provide Product Specific Certificate
              </CheckboxField>
              <SelectField name="certificate" label="Certificate">
                <SelectOption value="">---Select Certificate---</SelectOption>
              </SelectField>
            </Fragment>
          );
        }}
      </Form>
    );
  }

  public handleSubmit = () => {
    this.submitForm();
  }

  private onSubmit = (values: FormValues, actions: FormActions) => {
    this.props.onUpdate!('certificate', values);
    actions.setSubmitting(false);
  }
}

export default Certificate;

При нажатии следующего WorkflowButton состояние редукса обновляется путем передачи действия updateEnvironmentWorkflow. Действие выглядит так:

export interface UpdateEnvironmentWorkflow {
  type: Constants.UPDATE_ENVIRONMENT_WORKFLOW;
  payload: {
    key: string;
    value: any;
  };
}

export type CreateEnvironmentAction = UpdateEnvironmentWorkflow;

export const updateEnvironmentWorkflow = (
  key: string,
  value: any
): UpdateEnvironmentWorkflow => ({
  payload: { key, value },
  type: Constants.UPDATE_ENVIRONMENT_WORKFLOW
});

А мой редуктор похож на:

const createEnvironment = (
  state: CreateEnvironment = initialState.createEnvironment,
  action: CreateEnvironmentAction
) => {
  switch (action.type) {
    case Constants.UPDATE_ENVIRONMENT_WORKFLOW:
      return {
        ...state,
        [action.payload.key]: {
          ...state[action.payload.key],
          formValues: action.payload.value
        }
      };
    default:
      return state;
  }
};

export default createEnvironment;

Теперь странная часть заключается в том, что если я нажму следующую кнопку, состояние редукса обновится новыми значениями. Если я перейду на какую-то другую страницу и вернусь к созданию среды, в моих значениях формы будут отображаться обновленные значения из состояния избыточного хранилища.

НО, если я просто нажму предыдущую кнопку, мои значения состояния не будут отображать обновленные значения. Console.log (formValues) внутри render () сертификата показывает только начальные значения.

Любая помощь будет оценена. Спасибо.

Также initialValues ​​формы - это Formik initialValues. Это может быть проблема с formik

...