programing

구성요소는 어느 수준에서 Stores in Flux의 엔티티를 읽어야 합니까?

css3 2023. 3. 31. 22:35

구성요소는 어느 수준에서 Stores in Flux의 엔티티를 읽어야 합니까?

Flux를 사용하기 위해 앱을 다시 쓰고 있는데 Stores에서 데이터를 검색하는 데 문제가 있습니다.컴포넌트도 많고, 둥지도 많이 있습니다.큰 것도 .Article ).UserAvatar,UserLink를 참조해 주세요.

컴포넌트 계층에서 Stores의 데이터를 어디서 읽어야 할지 고민하고 있습니다.
는 두 가지 방법을 해 보았지만에 들지 않았다.

모든 엔티티 구성 요소가 자체 데이터를 읽습니다.

Store에서 일부 데이터가 필요한 각 구성 요소는 엔티티 ID만 수신하고 자체적으로 엔티티를 검색합니다.
를 들어, 「」라고 하는 것은,Article「」에됩니다.articleId,UserAvatar ★★★★★★★★★★★★★★★★★」UserLinkuserId.

이 방법에는 몇 가지 중대한 단점이 있습니다(코드 샘플에서 설명).

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>
    )
  }
});

이 접근법의 단점:

  • 100s 컴포넌트가 Stores에 가입할 가능성이 있다는 것은 매우 불만스러운 일입니다.
  • 각 컴포넌트가 개별적으로 데이터를 취득하기 때문에 데이터가 어떻게 갱신되고 어떤 순서로 갱신되는지를 추적하는 것은 어렵습니다.
  • 이미 엔티티가 있는 경우에도 엔티티의 ID를 강제로 하위에게 전달해야 합니다.하위 엔티티는 엔티티를 다시 취득합니다(그렇지 않으면 일관성이 깨집니다).

모든 데이터는 상위 레벨에서 한 번 읽혀져 컴포넌트에 전달됩니다.

버그를 추적하는 데 지쳤을 때, 모든 데이터를 최상위 레벨에 두려고 했습니다.그러나 일부 엔티티에서는 몇 가지 수준의 보금자리를 가지고 있기 때문에 이것은 불가능한 것으로 판명되었습니다.

예를 들어 다음과 같습니다.

  • A CategoryUserAvatar카테고리에 하고 있는 의 수
  • Article 개 수 Categorys.

"" 에서 Stores에서 Article , , , , , , 음 ,음 , , , , , 。

  • ArticleStore;
  • 기사의 를 든든 retrieve에서 합니다.CategoryStore;
  • 는, 각'' separ에서 개별적으로 합니다.UserStore;
  • 어떻게든 모든 데이터를 컴포넌트에 전달합니다.

더욱 실망스러운 것은 깊이 중첩된 엔티티가 필요할 때마다 추가로 전달하기 위해 중첩된 각 레벨에 코드를 추가해야 한다는 것입니다.

요약

두 방법 모두 결함이 있는 것으로 보입니다.어떻게 하면 이 문제를 가장 우아하게 해결할 수 있을까요?

목표:

  • 매장에 엄청난 수의 가입자가 있으면 안 된다. 같은 짓이다UserLink의 말을 듣다UserStore부모 컴포넌트가 이미 그렇게 하고 있는 경우.

  • 스토어에서 「」등).user 컴포넌트가 소품을 통해서도 통과할 수 있을 것 같아요.

  • 관계 추가 또는 삭제가 복잡하기 때문에 상위 수준에서 모든 엔티티(관계 포함)를 가져올 필요는 없습니다. 않다는 '다'를 ).curator를 참조해 주세요.

대부분의 사용자는 계층의 맨 위 근처에 있는 컨트롤러 뷰 컴포넌트에 있는 관련 스토어를 듣는 것으로 시작합니다.

나중에 많은 관련 없는 소품들이 계층 구조를 통해 깊이 중첩된 구성요소로 전달되는 것처럼 보일 때, 어떤 사람들은 더 깊은 구성요소가 가게의 변화를 듣도록 하는 것이 좋은 생각이라고 결정할 것이다.이를 통해 컴포넌트 트리의 이 깊은 분기에 해당하는 문제 도메인을 보다 효율적으로 캡슐화할 수 있습니다.이것을 현명하게 하는 데는 좋은 논거가 있다.

하지만 저는 항상 맨 위에서 듣고 모든 데이터를 단순히 전달하는 것을 선호합니다.때로는 가게의 전체 상태를 가져다가 하나의 오브젝트로 계층에 전달하기도 하고, 이것을 여러 점포에 대해 실시합니다.그래서 제가 소품을 하나 준비해서ArticleStore및 상태UserStore 중첩되지 않도록 플로우가 된다는 것을 알 수 컨트롤러 뷰가 깊이 중첩되지 않도록 하면 데이터의 단일 진입점이 유지되고 데이터 흐름이 통합됩니다.그렇지 않으면 데이터 소스가 여러 개 있기 때문에 디버깅이 어려워질 수 있습니다.

이 전략에서는 유형 확인이 더 어렵지만 React의 PropTypes를 사용하여 대형 객체 as-prop에 대한 "모양" 또는 유형 템플릿을 설정할 수 있습니다.참조: https://github.com/facebook/react/blob/master/src/core/ReactPropTypes.js#L76-L91 http://facebook.github.io/react/docs/reusable-components.html#prop-validation

저장소 자체에 있는 저장소 간에 데이터를 연결하는 논리를 넣을 수 있습니다. 당신의 ★★★★★★★★★★★★★★★★★★★.ArticleStore 수 있습니다.waitFor()UserStore 관련 Article에서 getArticles()뷰에서 이 작업을 수행하는 것은 뷰 레이어에 논리를 밀어 넣는 것처럼 들리는데, 이는 가능한 한 피해야 합니다.

'나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나transferPropsTo()많은 사람들이 이것을 좋아하지만, 저는 가독성과 유지보수를 위해 모든 것을 명확하게 하는 것을 선호합니다.

WWIW, 제가 알기로는 David Nolen은 Om 프레임워크(약간 Flux 호환성이 있음)에 대해 루트 노드 상의 단일 데이터 입력점을 가지고 있습니다. 즉, Flux에서는 컨트롤러 뷰가 1개만 모든 스토어에 대해 청취하는 것입니다.이것은, 다음과 같은 방법으로 효율화됩니다.shouldComponentUpdate()===와 참조로 비교할 수 있는 불변의 데이터 구조를 제공합니다.불변의 데이터 구조에 대해서는 David's mori 또는 Facebook의 불변의 js를 확인합니다.Om에 대한 나의 제한된 지식은 주로 JavaScript MVC 프레임워크의 미래에서 나온다.

제가 도착한 접근방식은 각 컴포넌트가 (ID가 아닌) 데이터를 소품으로 받는 것입니다.중첩된 일부 구성 요소에 관련된 엔티티가 필요한 경우 해당 엔티티를 검색하는 것은 상위 구성 요소에 달려 있습니다.

예에서는 " " " 입니다.Article 한다article할 수 있는 것은 「」입니다).ArticleList ★★★★★★★★★★★★★★★★★」ArticlePage를 참조해 주세요.

★★★★★★★★★★★★★★★★★★Article렌더링도 하고 싶다UserLink ★★★★★★★★★★★★★★★★★」UserAvatar는, 의 기사에 응모합니다.UserStore해 두겠습니다.author: UserStore.get(article.authorId)그 상태로.그런 다음 렌더링합니다.UserLink ★★★★★★★★★★★★★★★★★」UserAvatar이와 함께.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>
    )
  }
});

이렇게 하면 가장 안쪽의 컴포넌트는 멍청하게 유지되지만 최상위 컴포넌트를 복잡하게 만들지는 않습니다.

내 해결책은 훨씬 더 간단하다.독자적인 상태를 가지는 모든 컴포넌트는, 스토어에의 통화와 청취가 허가됩니다.이들은 매우 컨트롤러와 같은 컴포넌트입니다.상태를 유지하지 않고 렌더링만 하는 더 깊이 중첩된 구성 요소는 허용되지 않습니다.순수 렌더링 소품만 받습니다. 보기처럼요.

이렇게 하면 모든 것이 스테이트풀 컴포넌트에서 스테이트리스 컴포넌트로 흐릅니다.스테이트풀 카운트를 낮게 유지합니다.

당신의 경우, 기사는 스테이트풀하기 때문에 스토어 및 UserLink 등과 대화할 수 있습니다.그러면 article.user를 소품으로 받을 수 있습니다.

2개의 철학에 기재되어 있는 문제는 어느 한 페이지 어플리케이션에서도 공통입니다.

이 비디오에서는 간단하게 설명하겠습니다.https://www.youtube.com/watch?v=IrgHurBjQbg과 릴레이(https://facebook.github.io/relay )는 Facebook에 의해 개발되어 당신이 설명한 트레이드오프를 극복하고 있습니다.

릴레이의 접근방식은 매우 데이터 중심적입니다."이 뷰의 각 컴포넌트에 필요한 데이터만 서버에 대한1개의 쿼리로 취득하려면 어떻게 해야 합니까?"라는 질문에 대한 답변입니다.동시에 릴레이는 컴포넌트가 여러 뷰에서 사용되는 경우 코드 간에 커플링이 거의 발생하지 않도록 합니다.

릴레이가 선택사항이 아닌 경우, "모든 엔티티 컴포넌트가 자체 데이터를 읽습니다"라고 하는 것이 귀하가 설명한 상황에 더 적합한 접근법이라고 생각합니다.나는 플럭스의 오해가 가게라고 생각한다.스토어의 개념은 모델이나 오브젝트 컬렉션을 보관하는 장소가 되지 않습니다.저장소는 보기가 렌더링되기 전에 응용프로그램이 데이터를 저장하는 임시 장소입니다.실제로 존재하는 이유는 서로 다른 저장소의 데이터에 대한 의존성 문제를 해결하기 위해서입니다.

Flux는 스토어가 모델 및 객체 컬렉션(백본)의 개념과 어떻게 관련되어 있는지 명시하지 않았습니다.그런 의미에서 실제로 플럭스 스토어를 만들고 있는 사람도 있습니다.이것은 사용자가 브라우저를 계속 열어 두는 동안 평면이 아닌 특정 유형의 오브젝트 컬렉션을 넣는 장소입니다만, 플럭스라고 하는 것은 아닙니다.

해결책은 보기를 렌더링하는 데 필요한 엔티티(및 잠재적으로 더 많은 엔티티)가 저장되고 업데이트된 상태로 유지되는 다른 레이어를 갖는 것입니다.모델 및 컬렉션을 추상화하는 이 레이어를 사용하는 경우 하위 구성 요소가 자체 데이터를 가져오기 위해 다시 쿼리해야 해도 문제가 없습니다.

언급URL : https://stackoverflow.com/questions/25701168/at-what-nesting-level-should-components-read-entities-from-stores-in-flux