React, Redux, MUI-Datables, Redux-Form: ошибка Webpack - «TypeError: Невозможно прочитать свойство 'toString' из неопределенного - PullRequest
0 голосов
/ 21 декабря 2018

Я работал над проблемой в течение 3 дней и решил наконец опубликовать.

Технический стек : Зависимости:

    "dependencies": {
    "@material-ui/core": "^3.7.0",
    "@material-ui/icons": "^3.0.1",
    "axios": "~0.18.0",
    "classnames": "~2.2.6",
    "history": "^4.7.2",
    "lodash": "~4.17.11",
    "mui-datatables": "^2.0.0-beta-42",
    "prop-types": "~15.6.2",
    "react": "~16.7.0",
    "react-dom": "~16.7.0",
    "react-redux": "~6.0.0",
    "react-router-dom": "^4.3.1",
    "react-router-prop-types": "~1.0.4",
    "recompose": "~0.30.0",
    "redux": "^4.0.1",
    "redux-form": "~8.0.4",
    "redux-thunk": "^2.3.0"
  },

ОбщиеПроблема : при прохождении через приложение React я могу успешно перейти из моего корневого маршрута с помощью компонента Layout -> маршрут с компонентом PolicyList -> маршрут с компонентом PolicyEdit -> маршрут с компонентом PolicyForm.Однако, когда я щелкаю навигацию по макету обратно на другой маршрут, я получаю следующую ошибку:

TypeError: Невозможно прочитать свойство 'toString' из неопределенного bundle.js: 30- Image

Ожидаемое поведение : При переходе от формы избыточного числа (нажав кнопку Отправить ИЛИ навигацию по боковой панели), которая редактирует мои политики обратно к маршруту политики, который отображает все политики, данные MUI должны повторно отображаться.

Шаги для воспроизведения :

1) У меня есть компонент Layout, который использует MUI с навигацией боковой панели с базовыми компонентами Link React Router для перехода к конечным точкам 2)В App.js используется компонент «Маршрутизатор и история». 3) PolicyList отображает все политики из вызова API бэкэнда с помощью fetchPolicies создателя действия, а затем визуализирует данные с использованием таблиц данных MUI.Таблицы многоязыкового пользовательского интерфейса содержат компоненты Link для перехода к редактированию и удалению конечных точек. 4) Когда пользователь нажимает кнопку Edit Link, принимает компонент PolicyEdit, который вызывает PolicyForm для отображения содержимого на экране. 5) Если пользователь нажимает ссылку Navbar политики, чтобы вернуться к PolicyList, ошибкапроисходит

App.js

class App extends Component {
  render() {
    return (
      <div>
        <Router history={history}>
          <div>
            <Layout>
              <Switch>
                <Route path="/app/fusion" exact component={HomePage2} />
                <Route path="/app/fusion/policy" exact component={PolicyList} />
                <Route path="/app/fusion/policy/new" exact component={PolicyCreate} />
                <Route path="/app/fusion/policy/edit/:id" exact component={PolicyEdit} />
                <Route path="/app/fusion/policy/delete/:id" exact component={PolicyDelete} />
              </Switch>
            </Layout>
          </div>
        </Router>
      </div>
    );
  }
}

export default App;

PolicyList.js

class PolicyList extends React.Component {
componentDidMount() {
    this.props.fetchPolicies();
  }
renderPolicies() {
    return _.map(this.props.policies, policy => {
      // const policyLink = this.renderAdmin(policy);
      return [
        policy.resource.id,
        policy.resource.action,
        policy.resource.entity,
        `/app/fusion/policy/edit/${policy.resource.id}`,
        `/app/fusion/policy/delete/${policy.resource.id}`
      ];
    });
  }
render() {
    const columns = [
      'ID',
      'Action',
      'Entity',
      {
        name: 'Edit',
        options: {
          filter: false,
          customBodyRender: value => {
            console.log(this.props);
            return <Link to={value}>Edit</Link>;
          }
        }
      },
      {
        name: 'Delete',
        options: {
          filter: false,
          customBodyRender: value => {
            return (
              <Link to={value}>Delete</Link>
            );
          }
        }
      }
    ];

    const data = this.renderPolicies();
    const options = {
      filterType: 'checkbox',
      selectableRows: false,
    };

    return (
      <div>
        {this.renderCreate()}
        <br />
        <MUIDataTable
          title={'Policies'}
          data={data}
          columns={columns}
          options={options}
        />
      </div>
    );
  }

PolicyEdit.js

class PolicyEdit extends React.Component {
      componentDidMount() {
        this.props.fetchPolicy(this.props.match.params.id);
      }
      // callback on our form
      onSubmit = formValues => {
        this.props.editPolicy(this.props.match.params.id, formValues)
      };

      render() {
        if (!this.props.policy) {
          return <div>Loading...</div>;
        }
        return (
          <div>
            <h3>Edit Policy</h3>
            <PolicyForm
              initialValues={_.pick(this.props.policy, 'action', 'entity')}
              onSubmit={this.onSubmit}
            />
          </div>
        );
      }
    }

    const mapStateToProps = (state, ownProps) => {
      return {
        policy: state.policies[ownProps.match.params.id],
      };
    };

    export default connect(
      mapStateToProps,
      { fetchPolicy, editPolicy },
    )(PolicyEdit);

PolicyForm.js

class PolicyForm extends React.Component {
  componentDidMount() {
    console.log(this.props);
  }
  renderError(meta) {
    if (meta.touched && meta.error) {
      return (
        <div className="ui error message">
          <div className="header">{meta.error}</div>
        </div>
      );
    }
  }

  renderInput = formProps => {
    const className = `field ${
      formProps.meta.error && formProps.meta.touched ? 'error' : ''
    }`;
    return (
      <div className={className}>
        <label>{formProps.label}</label>
        <input {...formProps.input} />
        {this.renderError(formProps.meta)}
      </div>
    );
  };


  onSubmit = formValues => {
    this.props.onSubmit(formValues);
  };

  return (
      <form
        onSubmit={this.props.handleSubmit(this.onSubmit)}
        className="ui form error"
      >
        <Field
          name="action"
          component={this.renderInput}
          label="Enter Action"
        />
        <Field
          name="entity"
          component={this.renderInput}
          label="Enter Entity"
        />
        <button className="ui button primary">Submit</button>
      </form>
    );
  }
}

const validate = formValues => {
  const errors = {};
  if (!formValues.action) {
    errors.action = 'You must enter a action';
  }
  if (!formValues.entity) {
    errors.entity = 'You must enter a entity';
  }

  return errors;
};

export default reduxForm({
  form: 'policyForm',
  enableReinitialize: true,
  validate: validate
})(PolicyForm);
...