当前位置: 首页 > 面试题库 >

组件应在什么嵌套级别从Flux商店读取实体?

戚宏浚
2023-03-14
问题内容

我正在重写我的应用程序以使用Flux,但是从商店检索数据时遇到问题。我有很多组件,它们嵌套很多。其中有些是大(Article),有些是小而简单(UserAvatarUserLink)。

我一直在努力从组件存储层次结构中读取数据。
我尝试了两种极端的方法,但我都不喜欢:

所有实体组件都读取自己的数据

需要从Store获得一些数据的每个组件仅接收实体ID,并自行检索实体。
例如,Article被传递articleIdUserAvatarUserLink传递userId

此方法有几个重大缺点(在代码示例下讨论)。

var Article = React.createClass({
  mixins: [createStoreMixin(ArticleStore)],

  propTypes: {
    articleId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      article: ArticleStore.get(this.props.articleId);
    }
  },

  render() {
    var article = this.state.article,
        userId = article.userId;

    return (
      <div>
        <UserLink userId={userId}>
          <UserAvatar userId={userId} />
        </UserLink>

        <h1>{article.title}</h1>
        <p>{article.text}</p>

        <p>Read more by <UserLink userId={userId} />.</p>
      </div>
    )
  }
});

var UserAvatar = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    userId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      user: UserStore.get(this.props.userId);
    }
  },

  render() {
    var user = this.state.user;

    return (
      <img src={user.thumbnailUrl} />
    )
  }
});

var UserLink = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    userId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      user: UserStore.get(this.props.userId);
    }
  },

  render() {
    var user = this.state.user;

    return (
      <Link to='user' params={{ userId: this.props.userId }}>
        {this.props.children || user.name}
      </Link>
    )
  }
});

这种方法的缺点:

  • 令人沮丧的是,有100多个组件可能会订阅商店。
  • 由于每个组件都是独立检索数据的,因此 很难跟踪数据的更新方式和顺序
  • 即使您可能 已经 有一个实体处于状态,您还是被迫将其ID传递给子代,子代将再次检索它(或破坏一致性)。

所有数据在顶层都读取一次,然后传递给组件

当我厌倦了跟踪错误时,我试图将所有检索数据放在顶层。但是,事实证明这是不可能的,因为对于某些实体,我具有多个层次的嵌套。

例如:

  • 一个Category包含UserAvatar的谁该类别有助于人们的;
  • 一个Article可能有几个Category秒。

因此,如果我想以的级别从商店中检索所有数据,则Article需要:

  • 从中检索文章ArticleStore;
  • CategoryStore; 检索所有文章类别。
  • 从中分别检索每个类别的贡献者UserStore
  • 以某种方式将所有数据传递到组件。

更令人沮丧的是,每当我需要一个深度嵌套的实体时,我都需要向每个嵌套级别添加代码,以附加地传递它。

加起来

两种方法似乎都有缺陷。如何最优雅地解决这个问题?

我的目标:

  • 商店不应有疯狂的订户数量。如果父组件已经这样做,每个UserLink人都听不懂UserStore

  • 如果父组件已从存储中检索到某个对象(例如user),则我不希望任何嵌套的组件都必须再次获取它。我应该能够通过道具传递它。

  • 我不必在顶层获取所有实体(包括关系),因为这会使添加或删除关系复杂化。我不想每次嵌套实体获得新关系(例如category获得curator)时都在所有嵌套级别引入新道具。


问题答案:

我到达的方法是让每个组件都以道具的形式接收其数据(而不是ID)。如果某些嵌套组件需要相关实体,则取决于父组件来检索它。

在我们的示例中,Article应该有一个articleprop,它是一个对象(大概由ArticleList或检索ArticlePage)。

因为Article也要渲染UserLinkUserAvatar为文章的作者,它将订阅UserStore并保持author: UserStore.get(article.authorId)其状态。然后它将渲染UserLinkUserAvatar带有this
this.state.author。如果他们希望进一步传递下去,可以。没有子组件将需要再次检索该用户。

重申:

  • 没有组件会收到ID作为道具。所有组件都接收各自的对象。
  • 如果子级组件需要一个实体,则由父级负责检索它并作为道具传递。

这很好地解决了我的问题。使用此方法重写的代码示例:

var Article = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    article: PropTypes.object.isRequired
  },

  getStateFromStores() {
    return {
      author: UserStore.get(this.props.article.authorId);
    }
  },

  render() {
    var article = this.props.article,
        author = this.state.author;

    return (
      <div>
        <UserLink user={author}>
          <UserAvatar user={author} />
        </UserLink>

        <h1>{article.title}</h1>
        <p>{article.text}</p>

        <p>Read more by <UserLink user={author} />.</p>
      </div>
    )
  }
});

var UserAvatar = React.createClass({
  propTypes: {
    user: PropTypes.object.isRequired
  },

  render() {
    var user = this.props.user;

    return (
      <img src={user.thumbnailUrl} />
    )
  }
});

var UserLink = React.createClass({
  propTypes: {
    user: PropTypes.object.isRequired
  },

  render() {
    var user = this.props.user;

    return (
      <Link to='user' params={{ userId: this.props.user.id }}>
        {this.props.children || user.name}
      </Link>
    )
  }
});

这使最里面的组件保持愚蠢,但不会迫使我们使顶级组件复杂化。



 类似资料:
  • 问题内容: 我在我正在研究的项目中使用reactjs和助焊剂架构。我对如何将嵌套数据正确地拆分到存储中以及为什么应该将数据拆分到多个存储中感到困惑。 为了说明问题,我将使用以下示例: 想象一下您有项目的Todo应用程序。每个项目都有任务,每个任务都可以有注释。 该应用程序使用REST api检索数据,返回以下响应: 虚拟应用程序的界面在左侧显示一个项目列表,当您选择一个项目时,该项目变为活动状态,

  • 问题内容: 有两个链接 http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/composites.htm#LNPLS99981和 在Oracle中使用不同类型的PL /SQL集合的目的 通过引用以上两个链接,我有两个疑问 1.哪个是正确的嵌套表? 2.如果oracle文档是正确的,嵌套表和关联数组有什么区别? 问题答案: 这是另一个未知的区别

  • 我有一个包含两部分的简单程序:一个Spring5服务器,其中一个endpoint返回Mono 当我浏览到http://localhost:8080/rand返回一个双精度值。但是,当我使用客户机时,检索到的值始终为null(响应状态为200)。 我错过了什么?

  • 我试图在ObjectMapper的帮助下读取一个json文件(schools.json)。json的文件结构如下所示: 这个json文件是从java读取的,如下所示: 现在,上面的java代码块不工作了。schools对象返回NULL。 我不能让这个工作。我发现了一些json字段包含数组的例子,但我不能将类似的逻辑应用到我的例子中。感谢你的帮助。

  • 问题内容: Redux应用程序中的初始状态可以通过两种方式设置: 将其作为第二个参数传递给(docs link) 将其作为第一个参数传递给您的(子)还原器(docs链接) 如果将初始状态传递给商店,您如何从商店读取该状态并将其作为化简器中的第一个参数? 问题答案: TL; DR 没有或没有类似的手动代码,总是在化简器中胜出,因为传递给化简器的 是 和 不是 ,因此在这种情况下不会应用ES6参数语法