Я столкнулся с проблемой в последние несколько дней, которую я просто не могу взломать.
Что я пытаюсь сделать: У нас есть боковая панель, из которойВы можете выбрать « Study ».Это исследование определяет, что вы видите в основном блоке контента, так как каждое исследование имеет разные данные и пользователей, связанных с ним.В основном блоке контента у меня настроено форм , по одному для каждого пользователя.
Проблема: При загрузке первой страницы все работает нормально.Однако, если вы измените исследование , таким образом, визуализируя страницу заново с помощью componentWillReceiveProps, новые загруженные формы уже есть, но с пустыми значениями (без начальных значений) и инициализированными значение false
.Они также не могут быть выбраны никоим образом - сама форма представляет собой один выпадающий список и 3 флажка, и вы не можете выбрать ни один из них.
При обновлении страницы формы снова работают, даже нановое исследование.
Что я пробовал:
- Ручная инициализация форм с помощью
this.props.dispatch(initialize(form_name))
.Это приводит к тому, что формы инициализируются с правильными значениями, но по-прежнему невозможно каким-либо образом взаимодействовать с ними. - Обновление вручную (this.forceUpdate) при изменении родительского объекта обучения.Это ничего не изменило
- Установка
enableReinitialize
на true
- Предоставление
key
родительской странице, чтобы она каждый раз отображалась свежо (хак, я думал, будет работать, но я тожесделать это правильно, или это не сработало.) - Уничтожение старых форм при переключении учебного процесса
Вот код компонента Parent и компонента Form,Эта боковая панель находится в отдельном компоненте, если вы хотите увидеть это по какой-то причине, просто спросите.В этих файлах много чего происходит, в основном это другие посторонние элементы пользовательского интерфейса для приложения, но я отметил, где форма отображается в родительском файле с помощью //FORM IN QUESTION IS RENDERED HERE
.
PARENT
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import IconButton from 'material-ui/IconButton';
import Button from 'material-ui/Button';
import InviteUsersDialog from './InviteUsersDialog';
import SwipeableViews from 'react-swipeable-views';
import AppBar from 'material-ui/AppBar';
import Tabs, { Tab } from 'material-ui/Tabs';
import Avatar from 'material-ui/Avatar';
import tempAvatar from '../../Assets/temp-avatar.jpg';
import ExpansionPanel, {
ExpansionPanelDetails,
ExpansionPanelSummary,
} from 'material-ui/ExpansionPanel';
import Typography from 'material-ui/Typography';
import ExpandMoreIcon from 'material-ui-icons/ExpandMore';
import { withRouter } from 'react-router-dom';
import { withStyles } from 'material-ui/styles';
import { connect } from 'react-redux';
import { getUsersAction, getInvestigationPermissionsAction, resetUsersError, destroyFormsAction } from '../../actions/manage';
import { MenuItem } from 'material-ui/Menu';
import { Field, FieldArray, reduxForm, getFormValues, change, reset, destroy } from 'redux-form';
import {
Checkbox,
RadioGroup,
Select,
TextField,
Switch,
} from 'redux-form-material-ui'
import PermissionsForm from './PermissionsForm';
import compose from 'recompose/compose';
class Manage extends Component {
constructor(props) {
super(props);
if (this.props.investigation) {
this.props.getUsersAction(this.props.investigation)
}
}
state = {
inviteOpen: false,
expanded: null,
value: 0
}
componentWillReceiveProps(nextProps) {
if (this.props.investigation !== nextProps.investigation) {
this.props.getUsersAction(nextProps.investigation)
}
}
handleInviteOpen = () => {
this.setState({
inviteOpen: true
})
}
updateOnSave = () => {
this.setState({
expanded: null
})
this.props.getUsersAction(this.props.investigation).then(() => {
this.props.getInvestigationPermissionsAction(this.props.investigation)
})
}
closeOnCancel = () => {
this.setState({
expanded: null
})
}
closeDialog = () => {
this.setState({
inviteOpen: false
})
}
handleChange = (event, value) => {
console.log(value)
this.setState({ value });
};
handleChangeIndex = index => {
this.setState({ value: index });
};
handleExpansionChange = panel => (event, expanded) => {
this.setState({
expanded: expanded ? panel : false,
});
}
render() {
const { expanded } = this.state;
let inviteUsers = null;
if (this.state.inviteOpen === true) {
inviteUsers = (
<InviteUsersDialog open={this.state.inviteOpen} updateOnSave={this.updateOnSave} closeDialog={this.closeDialog}/>
)
} else {
inviteUsers = null;
}
if (this.props.usersError) {
this.props.history.push('/dash')
this.props.resetUsersError()
}
let usersList = null;
if (this.props.users) {
console.log("USERS:", this.props.users)
usersList = (
<div className={this.props.classes.usersExpansions}>
<ExpansionPanel className={this.props.classes.expansionPanel} expanded={false}>
<ExpansionPanelSummary className={this.props.classes.expansionSummary} expandIcon={<ExpandMoreIcon className={this.props.classes.headerExpandMore}/>}>
<div className={this.props.classes.headerAvatarContainer}>
<div className={this.props.classes.userInfo}>
<Typography className={this.props.classes.headingName}>Name</Typography>
<Typography className={this.props.classes.headingEmail}>Email</Typography>
</div>
</div>
<Typography className={this.props.classes.headerStatus}>Status</Typography>
<Typography className={this.props.classes.headerPermissions}>Permissions</Typography>
</ExpansionPanelSummary>
</ExpansionPanel>
{this.props.users.currentUsers.map((user) =>
<ExpansionPanel className={this.props.classes.expansionPanel} expanded={expanded === user.email + '-' + this.props.investigation} onChange={this.handleExpansionChange(user.email + '-' + this.props.investigation)}>
<ExpansionPanelSummary className={this.props.classes.expansionSummary} expandIcon={<ExpandMoreIcon />}>
<div className={this.props.classes.avatarContainer}>
<Avatar
alt={user.name}
src={user.avatarImg ? "data:image/jpeg;base64," + user.avatarImg : tempAvatar}
className={this.props.classes.avatar}
style={{ borderRadius: 2.1 }}
/>
<div className={this.props.classes.userInfo}>
<Typography className={this.props.classes.headingName}>{user.name}</Typography>
<Typography className={this.props.classes.headingEmail}>{user.email}</Typography>
</div>
</div>
<Typography className={this.props.classes.status}>{expanded === user.email + '-' + this.props.investigation ? '' : 'Activated'}</Typography>
<Typography className={this.props.classes.headingPermissions}>{expanded === user.email + '-' + this.props.investigation ? '' : user.permissionsArr.join(', ')}</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={this.props.classes.detailsContainer}>
//FORM IN QUESTION IS RENDERED HERE
<PermissionsForm
form={`PermissionsForm_${user.identifier + '-' + this.props.investigation}`}
updateOnSave={this.updateOnSave} closeOnCancel={this.closeOnCancel}
loggedInUser={user.email === localStorage.getItem('userEmail') ? true : false}
formName={`PermissionsForm_${user.identifier + '-' + this.props.investigation}`}
initialValues={{identifier: user.identifier, viewPermissions: user.permissions.viewEntries === true ? 'allEntries' : 'ownEntries', addEntriesPermissions: true, exportPermissions: user.permissions.export, manageInvestPermissions: user.permissions.manageInvest}}/>
</ExpansionPanelDetails>
</ExpansionPanel>
)}
{this.props.users.pendingUsers.map((user) =>
<ExpansionPanel className={this.props.classes.expansionPanel} expanded={false} onChange={this.handleExpansionChange(user.email + '-' + this.props.investigation)}>
<ExpansionPanelSummary className={this.props.classes.expansionSummary} expandIcon={<ExpandMoreIcon className={this.props.classes.headerExpandMore}/>}>
<div className={this.props.classes.avatarContainer}>
<Avatar
alt={user.name}
src={tempAvatar}
className={this.props.classes.avatar}
style={{ borderRadius: 0 }}
/>
<div className={this.props.classes.userInfo}>
<Typography className={this.props.classes.headingEmail}>{user.email}</Typography>
</div>
</div>
<Typography className={this.props.classes.status}>Pending</Typography>
<Typography className={this.props.classes.headingPermissions}>{user.permissionsArr.join(', ')}</Typography>
</ExpansionPanelSummary>
</ExpansionPanel>
)}
</div>
)
}
return (
<div className={this.props.classes.container}>
<div className={this.props.classes.pageHeaderContainer}>
<h2 className={this.props.classes.title}>Manage users</h2>
<Button color="primary" raised className={this.props.classes.inviteButton} onClick={this.handleInviteOpen}>Invite user</Button>
</div>
{inviteUsers}
<AppBar position="static" color="default" className={this.props.classes.tabsAppBar}>
<Tabs
value={this.state.value}
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
fullWidth
className={this.props.classes.tabs}
>
<Tab label="People" />
<Tab label="Groups" />
</Tabs>
</AppBar>
<SwipeableViews
axis={'x'}
index={this.state.value}
onChangeIndex={this.handleChangeIndex}
>
<div className={this.props.classes.peopleContainer}>
{usersList}
</div>
<div>
</div>
</SwipeableViews>
</div>
);
}
}
const styles = {
};
function mapStateToProps(state, ownProps) {
return {
investigation: state.manage.savedInvest,
users: state.manage.authorizedUsers,
usersError: state.manage.usersError
};
}
export default compose(
withRouter,
connect(mapStateToProps, {getUsersAction, getInvestigationPermissionsAction, resetUsersError, destroyFormsAction}),
withStyles(styles)
)(Manage);
ФОРМА
import React from 'react';
import Dialog, {
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from 'material-ui/Dialog';
import Button from 'material-ui/Button';
import Input, { InputLabel } from 'material-ui/Input';
import { withStyles } from 'material-ui/styles';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
import Typography from 'material-ui/Typography';
import Divider from 'material-ui/Divider'
import SelectBase from 'material-ui/Select';
import { MenuItem } from 'material-ui/Menu';
import { Field, FieldArray, reduxForm, getFormValues, change, reset, initialize } from 'redux-form';
import { patchPermissionsAction } from '../../actions/manage';
import { resetFormsAction } from '../../actions/dashboard';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import Tooltip from 'material-ui/Tooltip';
import PropTypes from 'prop-types';
import compose from 'recompose/compose';
import {
Checkbox,
RadioGroup,
Select,
TextField,
Switch,
} from 'redux-form-material-ui'
const required = value => (value == null ? 'Required' : undefined)
class PermissionsForm extends React.Component {
constructor(props) {
super(props);
}
static contextTypes = {
form: PropTypes.string
}
submit = (values) => {
this.props.patchPermissionsAction(values, this.props.investigation).then(() => {
this.props.updateOnSave();
})
}
handleCancel = () => {
this.props.closeOnCancel();
this.props.dispatch(reset(this.props.formName))
}
componentDidUpdate() {
console.log("!")
if(!this.props.initialized) {
console.log("!!")
}
}
componentWillUnmount() {
}
render() {
const { handleSubmit, pristine, reset, submitting } = this.props
let managePerm = null;
if (this.props.loggedInUser) {
managePerm = (
<Tooltip id="tooltip-top-start" title="Coming soon" placement="top">
<Typography className={this.props.classes.status}>Manage users</Typography>
</Tooltip>
)
} else {
managePerm = (<Typography className={this.props.classes.status}>Manage users</Typography>)
}
return (
<div className={this.props.classes.permFormContainer}>
<Divider />
<form onSubmit={ handleSubmit(this.submit) }>
<div className={this.props.classes.innerFormContainer}>
<div className={this.props.classes.groupsContainer}>
<br/>
</div>
<div className={this.props.classes.fieldContainer}>
<Typography className={this.props.classes.status}>View</Typography>
<Field name="viewPermissions" component={Select}>
<MenuItem value="ownEntries">View own entries</MenuItem>
<MenuItem value="allEntries">View all entries</MenuItem>
</Field>
</div>
<div className={this.props.classes.fieldContainer}>
<Tooltip id="tooltip-top-start" title="Coming soon" placement="top">
<Typography className={this.props.classes.status}>Add entries</Typography>
</Tooltip>
<Field
name="addEntriesPermissions"
component={Checkbox}
normalize={v => !!v}
disabled={true}
/>
</div>
<div className={this.props.classes.fieldContainer}>
<Typography className={this.props.classes.status}>Export data</Typography>
<Field
name="exportPermissions"
component={Checkbox}
normalize={v => !!v}
/>
</div>
<div className={this.props.classes.fieldContainer}>
{managePerm}
<Field
name="manageInvestPermissions"
component={Checkbox}
normalize={v => !!v}
disabled={this.props.loggedInUser === true ? true : false}
/>
</div>
</div>
<Divider />
<div className={this.props.classes.actionButtons}>
<Tooltip id="tooltip-top-start" title="Coming soon" placement="top">
<Button color="error" className={this.props.classes.deleteButton}>
Delete account
</Button>
</Tooltip>
<div className={this.props.classes.saveAndCancelButtons}>
<Button onClick={this.handleCancel} className={this.props.classes.cancelButton}>
Cancel
</Button>
<Button type="submit" disabled={submitting} color="primary" className={this.props.classes.saveButton}>
Save
</Button>
</div>
</div>
</form>
</div>
);
}
}
function mapStateToProps(state, ownProps) {
return {
investigation: state.manage.savedInvest,
investTitle: state.manage.savedInvestTitle
};
}
const styles = theme => ({
});
const reduxFormmPermissions = reduxForm({
enableReinitialize : true
})(PermissionsForm);
export default compose(
withRouter,
connect(mapStateToProps, {patchPermissionsAction}),
withStyles(styles)
)(reduxFormmPermissions);
Большое спасибо всем, кто может помочь мне разобраться в этом.Настоящий головорез.