MobX + React让我发疯

Art*_*nov -1 javascript mobx mobx-react

首先,我不是经验丰富的React开发人员。只是让你知道。

我有一家商店:

import {observable, action, reaction, computed, autorun} from 'mobx';
import scrollTo from 'react-scroll-to-component'
Run Code Online (Sandbox Code Playgroud)

ActivePostsStore类{

  @observable _posts = new Map()
  @observable _visiblePosts = new Set()

  @computed get visiblePosts() {
    return this._visiblePosts
  }

  @action
  addPost(uuid, ref) {
    // console.log('add post')
    this._posts.set(uuid, ref)
  }

  @action
  scrollToPost(uuid) {
    // console.log('scroll to post')
    scrollTo(this._posts.get(uuid), {})
  }

  @action
  addVisiblePost(uuid) {
    console.log('add vis post', this._visiblePosts.values())
    this._visiblePosts.add(uuid)
  }

  @action
  removeVisiblePost(uuid) {
    console.log('rem vis post', this._visiblePosts.values())
    this._visiblePosts = new Set([...this._visiblePosts].filter(el => el !== uuid))
  }

  // reacts = reaction(() => this._visiblePosts, () => console.log('===='))
  // reactToVisiblePosts() {
  //
  // }
}


const store = new ActivePostsStore()
export default store
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是,我可以在Layout Component或_document.js(我使用Next.js)中通过Provider传递存储。

/*Doesn't work. In root layout*/
<Provider store={ActivePostsStore}>
  <Content />
</Provider>
Run Code Online (Sandbox Code Playgroud)

每次尝试使用时,Provider我的商店都没有定义。在RootLayout或_document.js中也是如此。当然,我@observer为使用商店的组件提供了注释。但是存储仍未定义。

然后,我尝试使用@inject('activePostsStore')结果为Error,这告诉我,就像我根本没有提供任何商店一样。但是,实际上,我做到了。

所以!我决定直接注入它,就像:

@inject(() => ({
  store: ActivePostsStore
}))
@observer
Run Code Online (Sandbox Code Playgroud)

最后,我可以使用操作来添加或删除元素visiblePosts(我将其记录)。但!如果更改商店的状态,我的商店道具完全不响应。例如,它不会对将新条目添加到visiblePosts做出反应。如果重新加载页面,它甚至可能是不确定的。我的组件代码是:

render() {
    const {classes} = this.props
    return (
      <div className={classNames(classes.postsTree)}>
        {this.props.store.visiblePosts}
        {this.state.groupedDates !== undefined && this.state.groupedDates.map(([date, posts], index) =>
          <PostsTreeGroup
            active={_.some(posts.map(([uuid]) => uuid), uuid => this.props.store.visiblePosts.has(uuid))}
            key={date}
            date={date}
            posts={posts}/>
        )}
      </div>
    )
  }
Run Code Online (Sandbox Code Playgroud)

有人可以帮我使事情正常吗!

Dan*_*iel 5

问题1:

提供程序仅在您希望在组件中显示商店的组件上调用注入时才起作用。因此,您必须调用inject,否则商店是未定义的(因为没有人为您的商店设置组件的属性)。

传递给注入的字符串必须与您在提供程序中给定的属性名称完全相同。

你有:

<Provider store={ActivePostsStore}> // store is the property name
Run Code Online (Sandbox Code Playgroud)

所以你也必须打电话

@inject('store')
Run Code Online (Sandbox Code Playgroud)

然后,mobx查找密钥库,在您的提供程序中找到它,并将其分配给您的组件。

问题2:

您将计算商店中可见的帖子,而不是相反。因此方法visiblePosts仅返回可见的帖子。

商店:

@computed get visiblePosts() {
  return this._visiblePosts.map(uuid => this._posts.get(uuid));
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的组件中,您只能渲染可见的帖子:

零件:

this.props.store.visiblePosts.map(post => {
 return <PostsTreeGroup ...>
})
Run Code Online (Sandbox Code Playgroud)

我还看到您在进行某种排序?

然后,您将告诉商店如何排序(例如,设置属性),然后让商店在visiblePosts方法中进行排序。