Я работаю со следующим подключенным компонентом.
Содержит два раскрывающихся списка; родитель и ребенок. Когда родительский раскрывающийся список изменяется, он заполняет дочерний раскрывающийся список.
Параметры раскрывающегося списка извлекаются из API в родительском компоненте и сохраняются в хранилище Redux.
При первом отображении компонента, опция по умолчанию 'TELEVISION (T)' должна быть выбрана в раскрывающемся списке родителя и 'TV' в дочернем фильтре.
У меня есть два экземпляра компонента. Когда раскрывающиеся значения изменяются в одном экземпляре, это должно быть реплицировано в другом экземпляре. Это работает, как и ожидалось, с раскрывающимся списком родителей, но не с раскрывающимся списком дочерних элементов.
Примите во внимание любые советы о том, что мне нужно изменить, чтобы синхронизировать c выбранную дочернюю опцию в обоих случаях.
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Dropdown } from 'semantic-ui-react';
import {
changeParent,
changeChild
} from '../../actions/menuFiltersActions';
import makeDropdownOptions from '../../lib/makeDropdownOptions';
export class ParentChildFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
children: []
};
this.TELEVISION = 'TELEVISION';
this.TV = 'TV';
this.changeParent = this.changeParent.bind(this);
this.changeChild = this.changeChild.bind(this);
}
componentDidMount() {
if (this.props.parentChild.data.length) {
// eslint-disable-next-line
const { parentId, childId } = this.parentChildId();
this.changeParent(parentId);
}
}
componentDidUpdate(prevProps) {
if (prevProps.parentChild.data !== this.props.parentChild.data) {
// eslint-disable-next-line
const {parentId, childId} = this.parentChildId();
this.changeParent(parentId);
}
}
/**
* Find the parentChild id for TELEVISION and booking id for TV.
*/
parentChildId() {
const tvMedia = this.props.parentChild.data.find(m => m.name.indexOf(this.TELEVISION) !== -1);
const parentId = tvMedia && 'id' in tvMedia ? tvMedia.id : this.props.parentChild.data[0].id;
const tvBooking = this.props.parentChild.data.find(
m => m.id === parentId
).children.find(b => b.name === this.TV);
const childId = tvBooking && 'id' in tvBooking ? tvBooking.id : this.props.parentChild.data.find(
m => m.id === parentId
).children[0].id;
return { parentId, childId };
}
/**
* When a user selects a Parent from a filter display the associated children.
* When a user selects Parent TELEVISION, display Booking TV as default.
* @param {*} id integer id of user selected Media.
*/
changeParent(id) {
// Get the TELEVISION Media id and TV Booking id.
const { parentId, childId } = this.parentChildId();
// Fetch the children associated with the selected Media id.
const { children } = this.props.parentChild.data.find(m => m.id === id);
// If the user is selecting TELEVISION Media, display TV booking by default.
const wantedTvBookingId = id === parentId
? childId
: this.props.parentChild.selectedBooking;
let selectedBooking = children.find(b => (b.id === wantedTvBookingId));
selectedBooking = selectedBooking
? selectedBooking.id
: children[0].id;
this.props.changeParent(id);
this.setState({ children }, () => this.changeChild(selectedBooking));
}
changeChild(id) {
this.props.changeChild(id);
}
render() {
return (
<>
<span id="parentChild-label">Media Name</span>
<Dropdown
fluid
selection
loading={!this.props.parentChild.data.length}
placeholder="Select a Media"
options={makeDropdownOptions(this.props.parentChild.data, 'name', 'id')}
value={this.props.parentChild.selectedMedia}
onChange={(e, { value }) => this.changeParent(value)}
aria-labelledby="parentChild-label"
/>
<span id="booking-category-label">Booking Category</span>
<Dropdown
fluid
selection
loading={!this.state.children.length}
placeholder="Select a Booking Category"
options={makeDropdownOptions(this.state.children, 'name', 'id')}
value={this.props.parentChild.selectedBooking}
onChange={(e, { value }) => this.changeChild(value)}
aria-labelledby="booking-category-label"
/>
</>
);
}
}
ParentChildFilter.propTypes = {
parentChild: PropTypes.exact({
data: PropTypes.array,
selectedMedia: PropTypes.number,
selectedBooking: PropTypes.number
}).isRequired,
changeParent: PropTypes.func.isRequired,
changeChild: PropTypes.func.isRequired
};
export default connect(
store => ({
parentChild: store.menuFilters.parentChild
}),
{
changeParent,
changeChild
}
)(ParentChildFilter);