Я, вероятно, упускаю здесь что-то очень простое, но я не могу заставить свой код работать правильно. Я пытаюсь отобразить вложенный неупорядоченный список referenceListItems
для каждого referenceList
. Думаю, главный вопрос заключается в том, как передать переменную состояния referenceListItems
в дочерний компонент ReferenceListItems
?
const ReferencePage = () => (
<div>
<h1>Reference</h1>
<Reference />
</div>
);
class ReferenceBase extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
referenceLists: [],
referenceListItems: [],
};
}
componentDidMount() {
this.onListenForReferenceLists();
this.onListenForReferenceListItems();
}
onListenForReferenceLists() {
this.setState({ loading: true });
this.unsubscribeReferenceLists = this.props.firebase
.referenceLists()
.onSnapshot(snapshot => {
if (snapshot.size) {
let referenceLists = [];
snapshot.forEach(doc =>
referenceLists.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
referenceLists: referenceLists,
loading: false
});
} else {
this.setState({ referenceLists: null, loading: false });
}
});
}
onListenForReferenceListItems() {
this.unsubscribeReferenceListsItems = this.props.firebase
.referenceListItems()
.onSnapshot(snapshot => {
if (snapshot.size) {
let referenceListItems = [];
snapshot.forEach(doc =>
referenceListItems.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
referenceListItems: referenceListItems,
loading: false
});
} else {
this.setState({ referenceListItems: null, loading: false });
}
});
}
componentWillUnmount() {
this.unsubscribeReferenceLists();
this.unsubscribeReferenceListsItems();
}
render() {
const { referenceLists, referenceListItems, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{referenceLists ? (
<ReferenceLists referenceLists = {referenceLists} />
):(
<div>There are no reference items ...</div>
)}
</div>
);
}
}
const Reference = withFirebase(ReferenceBase);
const ReferenceLists = ({ referenceLists }) => (
<ul className = "reference-lists">
{referenceLists.map( referenceList => (
<ReferenceList key = {referenceList.uid} referenceList = {referenceList} />
))}
</ul>
);
const ReferenceList = ({ referenceList }) => (
<li className = "reference">
<strong>{referenceList.userId}</strong> {referenceList.name}
<ReferenceListItems />
</li>
);
const ReferenceListItems =({ referenceListItems }) => (
<ul className = "reference-list-items">
{referenceListItems.map( referenceListItem => (
<ReferenceListItem key = {referenceListItem.uid} referenceListItem = {referenceListItem} />
))}
</ul>
);
const ReferenceListItem = ({ referenceListItem }) => (
<li className = "reference-list-item">
<strong>{referenceListItem.userId}</strong> {referenceListItem.name}
</li>
);
Нет, я бы не хотел создавать для него еще один класс, так как это очень простое отображение. Сейчас это компонент без гражданства.
Переобъявив referenceList
let referenceLists = [];
он никогда не устанавливается в вашем классе. вам нужно либо вернуть referenceLists внутри закрытия, либо установить переменную уровня класса в вашем обратном вызове
this.referenceLists.push({ ...doc.data(), uid: doc.id })
Он устанавливается в вызове рендеринга (если вы это имеете в виду). У меня нет проблем с отображением списков ссылок, только подэлементов.
извините за ошибку, я думаю, что это - это то, что вы ищете
Вы явно не используете свой ReferenceListItems
внутри родительского ReferenceBase
компонента. Так что вам просто нужно передать его как свойство по всему дереву компонентов.
render() {
const { referenceLists, referenceListItems, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{referenceLists ? (
<ReferenceLists referenceLists = {referenceLists} referenceListItems = {referenceListItems} />
):(
<div>There are no reference items ...</div>
)}
</div>
);
const ReferenceLists = ({ referenceLists, referenceListItems }) => (
<ul className = "reference-lists">
{referenceLists.map( referenceList => (
<ReferenceList key = {referenceList.uid} referenceList = {referenceList} referenceListItems = {referenceListItems} />
))}
</ul>
const ReferenceList = ({ referenceList, referenceListItems }) => (
<li className = "reference">
<strong>{referenceList.userId}</strong> {referenceList.name}
<ReferenceListItems referenceListItems = {referenceListItems}/>
</li>
);
Спасибо! Вы бы предложили такой подход? (это кажется довольно утомительным)
вы могли бы поменять параметры компонентов, чтобы ваш ответ выглядел иначе. Я не вижу разницы между вашим ответом и тем, который был написан до вашего.
@Пим. Всегда пожалуйста! Глядя на то, как вы настроили эти компоненты, я думаю, что это будет самое простое решение для реализации. Вы также можете изучить API React.Context: reactjs.org/docs/context.html. Это позволяет вам передавать реквизиты из HOC глубоко вложенным дочерним компонентам без необходимости утомительно передавать их вниз. Но это заставит вас переосмыслить дерево компонентов.
@TenTenPeter Кристофер сначала задал несколько вопросов в комментариях, поэтому я принял его ответ вместо другого. Кроме того, ответ более полный.
@Pim, спасибо за отзыв, решение выше сработало для вас?
@ChristopherNgo Так и было, но я столкнулся с некоторыми другими проблемами при добавлении дополнительных функций. Возможно, придется объявить ReferenceListItems
полноценным компонентом.
@ Пим ааа, понятно. Я полагал, что ReferenceListItems в конечном итоге должен будет управлять своим собственным состоянием и т. д. Вероятно, ему нужно будет сделать его компонентом класса. В любом случае передача реквизита в него должна быть одинаковой.
@Pim также вместо того, чтобы передавать данные в качестве реквизита, используйте избыточность, которую легко реализовать redux.js.org/introduction/getting-started
@Pim Я просто констатировал очевидное, у меня ни с кем нет проблем.
Определены ли ReferenceListItems в другом файле?