我刚刚开始使用flux(现在使用redux),我想知道如何处理关系.
举个例子,我们可以使用Trello,它有包含卡的列的板.
一种方法是为板子安装一个存储/减速器,并在其中包含所有数据,但这意味着一些非常胖的存储,因为它们必须包含列和卡的所有操作.
我见过的另一种方法是将嵌套资源分成例如BoardStore,ColumnStore和CardStore,并使用它们的id作为参考.
这是一个我有点困惑的例子:你可以有一个名为addCard的动作创建者向服务器发出请求,创建一张包含所有数据的卡片.如果您正在进行乐观更新,您之前会在您的某个商店中创建一个卡片对象,但在您收到请求之前,您无法知道它将具有的ID.
简而言之:
有没有推荐的方法来处理这个案子?嵌套的存储/缩减器对我来说看起来有点傻,但是否则你最终会得到非常复杂的存储,所以它看起来真的很妥协.
我有登录组件,该组件应该可供未经身份验证的用户使用.在身份验证之后,此组件应该变得不可用.
var routes = (
<Route handler={App}>
<Route name="signIn" handler={signIn}/>
{/* redirect, if user is already authenticated */}
{ localStorage.userToken ? (
<Redirect from="signIn" to="/user"/>
) : null
}
</Route>
);
Router.run(routes, (Handler, state) => {
React.render(<Handler {...state}/>, document.getElementById('main'));
});
Run Code Online (Sandbox Code Playgroud)
如果用户在身份验证后因任何原因重新加载了webapp,则此代码非常有用,但当然如果用户没有重新加载webapp,则不会.我试图使用this.context.router.transitionToSignUp组件,但它工作得很糟糕 - 组件被渲染,然后这个脚本被执行.
所以我想将重定向权限添加到routes变量中,以使路由器重定向,甚至不用尝试渲染组件.
想象一下像Quora这样的东西.
[
{
type: "question",
answers: [
{
type: "answer",
upvotes: [
{
type: "upvote"
}
/* more upvotes */
],
comments [
{
type: "comment"
}
/* more comments */
]
}
/* more answers */
]
}
/* more questions */
]
Run Code Online (Sandbox Code Playgroud)
我肯定会有类似的东西QuestionsStore.但对于所有儿童实体,我不确定如何处理它们.来自Backbone我认为每个答案应该有一个UpvotesStore和一个CommentsStore组件将从这些商店获取他们的数据并订阅他们的更新.据我所知,Flux,"儿童"/关系商店有点不常见.
当每个组件订阅更新时QuestionsStore,会导致类似:
/* in CommentsComponent */
onUpdate: function() {
this.setState({
comments: QuestionsStore.getComments({questionId: 1, answerId: 1});
});
}
Run Code Online (Sandbox Code Playgroud)
或更极端:
/* in CommentComponent */
onUpdate: function() {
this.setState(QuestionsStore.getComment({questionId: …Run Code Online (Sandbox Code Playgroud) 我正在使用Facebook的Flux Dispatcher创建一个简单的CRUD应用程序来处理英语学习网站的帖子的创建和编辑.我目前正在处理一个看起来像这样的api:
/posts/:post_id
/posts/:post_id/sentences
/sentences/:sentence_id/words
/sentences/:sentence_id/grammars
Run Code Online (Sandbox Code Playgroud)
在应用程序的显示和编辑页面上,我希望能够在一个页面上显示给定帖子的所有信息以及所有句子和句子的单词和语法详细信息.
我遇到的问题是弄清楚如何启动收集所有这些数据所需的所有异步调用,然后将我需要的数据从所有存储组合成一个对象,我可以将其设置为我的顶级组件中的状态.我一直在尝试做的一个当前(可怕)的例子是:
顶级PostsShowView:
class PostsShow extends React.Component {
componentWillMount() {
// this id is populated by react-router when the app hits the /posts/:id route
PostsActions.get({id: this.props.params.id});
PostsStore.addChangeListener(this._handlePostsStoreChange);
SentencesStore.addChangeListener(this._handleSentencesStoreChange);
GrammarsStore.addChangeListener(this._handleGrammarsStoreChange);
WordsStore.addChangeListener(this._handleWordsStoreChange);
}
componentWillUnmount() {
PostsStore.removeChangeListener(this._handlePostsStoreChange);
SentencesStore.removeChangeListener(this._handleSentencesStoreChange);
GrammarsStore.removeChangeListener(this._handleGrammarsStoreChange);
WordsStore.removeChangeListener(this._handleWordsStoreChange);
}
_handlePostsStoreChange() {
let posts = PostsStore.getState().posts;
let post = posts[this.props.params.id];
this.setState({post: post});
SentencesActions.fetch({postId: post.id});
}
_handleSentencesStoreChange() {
let sentences = SentencesStore.getState().sentences;
this.setState(function(state, sentences) {
state.post.sentences = sentences;
});
sentences.forEach((sentence) => {
GrammarsActions.fetch({sentenceId: sentence.id})
WordsActions.fetch({sentenceId: sentence.id})
}) …Run Code Online (Sandbox Code Playgroud) 为了响应状态变化,我想触发另一个状态变化.这本质上是一个坏主意吗?
特定类型的场景是组件被建模为状态机,根据值来呈现不同的信息this.state.current_state.但外部事件可以通过通量存储器改变状态来提示它经历状态转换.这是一个人为的想法来实现这个想法:
我认为正确的生命周期方法是这样做的shouldComponentUpdate.这样的效果:
shouldComponentUpdate: function(nextProps, nextState) {
if (nextState.counter > 4 && this.state.current_state !== DISPLAY_MANY) {
this.setState({ current_state: DISPLAY_MANY });
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
在某些子组件中,counter可能会增加,所以counter我不想根据某个变量的值推断它会显示什么,而是想明确地编码状态.
真实场景比这更复杂,但希望这个场景足够详细,以便了解这个想法.做我正在想的事情可以吗?
编辑:修复代码示例,以避免通过添加额外的状态条件触发无限循环
所以说你有这个组件结构的聊天应用程序:
<ChatApp>
<CurrentUserInfo>...</CurrentUserInfo>
<ChatsPanel>...</ChatsPanel>
<SelectedChatPanel>
<MessagesList>
<MessageBaloon>
<MessageText></MessageText>
<MessageUserHead></MessageUserHead>
</MessageBaloon>
...
</MessagesList>
<SelectedChatPanel>
</ChatApp>
Run Code Online (Sandbox Code Playgroud)
和Redux状态一样:
{
currentUser: ...,
chatsList: ...,
selectedChatIndex: ...,
messagesList: [ ... ]
}
Run Code Online (Sandbox Code Playgroud)
如何将当前用户信息提供给<MessageUserHead>组件(将为每条消息呈现当前用户缩略图),而不必通过所有中间组件从根组件一直传递它?
同样,如何在不借助于暴露整个状态对象的情况下,如何为组件树中的每个表示/哑组件提供当前语言,主题等信息?
我想知道两者之间的关系.我很困惑,因为我认为它们都是管理状态的方法,而且似乎有重叠,所以我正在寻求一个概念上的区别,我可以应用以找出哪些信息可以保留在哪里以及如何使它们工作一起.有什么建议?
在过去的几个月里,我一直在学习React和Flux,而我还没有处理过的一件事就是向用户显示错误信息.具体而言,在flux action creator方法中由于ajax http请求而发生的错误消息.
一个简单的例子是用户登录 - 如果由于密码错误导致ajax请求中的登录失败,则服务器会以失败进行响应.那时,在我的flux动作创建器方法中,我唯一的选择是调度包含错误信息的动作,对吧?
我可以发送错误信息并将该错误保存在商店中.不过,我不确定将某些错误绑定到某些组件的最佳方法是什么.假设我的react组件树正在呈现多个错误感知组件,但在服务器端用户身份验证尝试期间发生错误,并且需要在该登录表单中显示.
是否有良好的模式或惯例来存储错误并知道它们适用于哪个组件?是否有一种编程方式来确定这一点,而不是将一些标识符传递给每个动作创建者函数,该函数标识动作创建者被称为它的组件等?
我的Action类型定义如下:
type Action =
{ type: 'DO_X' }
|
{ type: 'DO_Y', payload: string }
|
{ type: 'DO_Z', payload: number }
Run Code Online (Sandbox Code Playgroud)
它是一种联合类型,其中每个成员都是有效的动作.
现在我想创建一个createAction接受type并返回一个接受的新函数的函数payload.
const doZ = createAction('DO_Z')
console.log(doZ(42)) // { type: 'DO_Z', payload: 42 }
Run Code Online (Sandbox Code Playgroud)
这是我目前的实施:
const createAction = (type: Action['type']) =>
(payload?: any) =>
({ type, payload })
Run Code Online (Sandbox Code Playgroud)
它type像我想要的那样.我怎么能进行类型检查payload呢?我想payload基于匹配正确动作的类型type.例如,doZ使用a调用时应该失败,string因为它payload表示它只接受number.
我一直在使用 Vuex,它坚持只通过它改变状态,mutators或者actions让我认为你的商店应该只包含尽可能平坦的对象,只有原始类型。
一些线程甚至规定规范化您的数据(因此,不是嵌套对象树,而是具有带有 id 数组的对象来指示树关系)。这可能与您的 JSON api 非常匹配。
这让我认为在您的通量存储中存储类(可能有改变自己的方法)是一种反模式。事实上,即使将您商店的数据混合到一个类中,似乎您也在逆潮流而动,除非您的类不对它的内部数据进行任何修改。
这让我想到,在 Vue/Vuex/Reactive/Flux 中使用任何类是一种反模式吗?
这些库似乎明确设计为与普通 JS 对象一起使用,并且您与 API 的一般交互(数据输入、数据输出)让我觉得更实用的方法(无不变性)是原始设计者所考虑的。
编写从function => test => state mutator wrapper around function.
我知道 JS 对象和 JS 类的行为非常相似(并且基本上是同一件事),但我的逻辑是,如果您不考虑类进行设计,那么您更有可能不会用非通量污染您的状态状态变化。
社区中是否普遍认为您的通量代码应该更实用,更少面向对象?
flux ×10
reactjs ×8
redux ×5
javascript ×4
reactjs-flux ×3
es6-class ×1
graphql ×1
react-redux ×1
react-router ×1
typescript ×1
union ×1
vue.js ×1
vuex ×1