Я работал над проблемой в течение 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);