Заполнение свойств дочернего компонента без состояния из состояния родительского компонента для отображения вложенного неупорядоченного списка в React (с Firebase)

Я, вероятно, упускаю здесь что-то очень простое, но я не могу заставить свой код работать правильно. Я пытаюсь отобразить вложенный неупорядоченный список 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>
);

Определены ли ReferenceListItems в другом файле?

Chris Ngo 27.05.2019 22:23

Нет, я бы не хотел создавать для него еще один класс, так как это очень простое отображение. Сейчас это компонент без гражданства.

Pim 27.05.2019 22:24
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Переобъявив referenceList

let referenceLists = [];

он никогда не устанавливается в вашем классе. вам нужно либо вернуть referenceLists внутри закрытия, либо установить переменную уровня класса в вашем обратном вызове

this.referenceLists.push({ ...doc.data(), uid: doc.id })

Он устанавливается в вызове рендеринга (если вы это имеете в виду). У меня нет проблем с отображением списков ссылок, только подэлементов.

Pim 27.05.2019 22:31

извините за ошибку, я думаю, что это - это то, что вы ищете

Dataminion 27.05.2019 22:37
Ответ принят как подходящий

Вы явно не используете свой 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>
);

Спасибо! Вы бы предложили такой подход? (это кажется довольно утомительным)

Pim 27.05.2019 23:04

вы могли бы поменять параметры компонентов, чтобы ваш ответ выглядел иначе. Я не вижу разницы между вашим ответом и тем, который был написан до вашего.

TenTen Peter 27.05.2019 23:06

@Пим. Всегда пожалуйста! Глядя на то, как вы настроили эти компоненты, я думаю, что это будет самое простое решение для реализации. Вы также можете изучить API React.Context: reactjs.org/docs/context.html. Это позволяет вам передавать реквизиты из HOC глубоко вложенным дочерним компонентам без необходимости утомительно передавать их вниз. Но это заставит вас переосмыслить дерево компонентов.

Chris Ngo 27.05.2019 23:13

@TenTenPeter Кристофер сначала задал несколько вопросов в комментариях, поэтому я принял его ответ вместо другого. Кроме того, ответ более полный.

Pim 27.05.2019 23:19

@Pim, спасибо за отзыв, решение выше сработало для вас?

Chris Ngo 27.05.2019 23:20

@ChristopherNgo Так и было, но я столкнулся с некоторыми другими проблемами при добавлении дополнительных функций. Возможно, придется объявить ReferenceListItems полноценным компонентом.

Pim 27.05.2019 23:23

@ Пим ааа, понятно. Я полагал, что ReferenceListItems в конечном итоге должен будет управлять своим собственным состоянием и т. д. Вероятно, ему нужно будет сделать его компонентом класса. В любом случае передача реквизита в него должна быть одинаковой.

Chris Ngo 27.05.2019 23:25

@Pim также вместо того, чтобы передавать данные в качестве реквизита, используйте избыточность, которую легко реализовать redux.js.org/introduction/getting-started

Junius L. 27.05.2019 23:34

@Pim Я просто констатировал очевидное, у меня ни с кем нет проблем.

TenTen Peter 29.05.2019 16:56

Другие вопросы по теме