【问题标题】:Populating stateless child component props from parent component state to display nested unordered list in React (with Firebase)从父组件状态填充无状态子组件道具以在 React 中显示嵌套的无序列表(使用 Firebase)
【发布时间】:2019-05-27 20:20:15
【问题描述】:

我可能在这里遗漏了一些非常简单的东西,但我无法让我的代码正常运行。我正在尝试为每个referenceList 显示referenceListItems 的嵌套无序列表。我猜的主要问题是如何将状态变量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 是否定义在另一个文件中?
  • 不,我想避免为它创建另一个类,因为它只是一个非常简单的显示。它现在是一个无状态组件。

标签: reactjs state react-props


【解决方案1】:

您没有在父 ReferenceBase 组件中明确使用您的 ReferenceListItems。因此,您只需将其作为属性传递到整个组件树即可。

  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。不客气!看看您设置这些组件的方式,我认为这将是最容易实现的解决方案。您还可以查看 React.Context api:reactjs.org/docs/context.html。这使您可以将来自 HOC 的 props 传递给深度嵌套的子组件,而无需繁琐地传递它。但是,这会迫使你重新考虑你的组件树。
  • @Pim 啊,我明白了。我认为 ReferenceListItems 最终将需要管理它自己的状态等。可能需要使其成为一个类组件。无论如何,将 props 传递给它应该是相同的。
  • @Pim 也不是将数据作为 props 向下传递,使用 redux 很容易实现 redux.js.org/introduction/getting-started
【解决方案2】:

通过重新声明referenceList

let referenceLists = [];

它永远不会在您的班级中设置。你要么需要在闭包中返回referenceLists,要么在你的回调中设置类级变量

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

【讨论】:

  • 它确实在渲染调用中设置(如果这就是你的意思)。我没有问题显示参考列表,只有子项目。
  • 对不起我的错误我认为this是你要找的
猜你喜欢
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2020-05-08
  • 2020-07-25
相关资源
最近更新 更多