我已经解决了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);