React,Redux,MUI-Datables,Redux表单:Webpack错误-“ TypeError:无法读取未定义的属性'toString'

时间:2018-12-21 16:39:40

标签: reactjs webpack redux react-router redux-form

我已经解决了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: Cannot read property 'toString' of undefined bundle.js:30- Image

预期的行为:当从将我的策略重新编辑为呈现所有策略的策略路由的Redux表单(单击“提交”或侧边栏导航)进入时,MUI数据表应重新呈现。

复制步骤

1)我有一个布局组件,该组件将MUI与带有基本Link React Router组件的侧边栏导航一起使用到端点 2)App.js使用路由器和历史记录组件 3)PolicyList使用动作创建者fetchPolicies显示来自后端API调用的所有策略,然后使用MUI数据表呈现数据。 MUI数据块包含用于编辑和删除端点的链接组件 4)当用户按下Edit Link时,进入PolicyEdit组件,该组件调用PolicyForm在屏幕上呈现内容 5)如果用户按下策略导航栏链接返回到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);

0 个答案:

没有答案