在不传递道具的情况下管理嵌套的 Redux 容器?

Managing nested Redux containers without passing props?

给定这样的组件层次结构:

<TodoList>
  <Todo>
    <TodoHeader/>
    <TodoBody>
      <TodoDetails>
        <TodoStatus />
      <TodoDetails>
      <TodoDescription />
    <TodoBody>
  <Todo>
</TodoList>

...还有这样的商店:

{
  todos: [
    { id: 1, status: "INCOMPLETE", header: "title one", description: "do a something" },
    { id: 2, status: "INCOMPLETE", header: "title two", description: "something else" },
    { id: 3, status: "COMPLETE", header: "title three", description: "one more thing" },
  ]
}

嵌套的 TodoStatus 组件是否有一个很好的方法来连接到商店而不必向下传递 id 组件层次结构作为道具?例如,Todo 可以将 currentTodoId = 1 设置为上下文,这将可用 对于 child reducers,但是还有其他选择吗?也许是父组件将商店减少到的一种方式 子组件可以看到的单个待办事项...?

此时,您可能想问"why"?好吧,考虑一下 TodoList(对待办事项数组进行操作)和嵌套 TodoStatus(只想对单个待办事项进行操作)之间可能存在多个级别的严格表示组件.必须通过这样的层次结构向下传递 todoId 非常痛苦:

<TodoList>
  <Todo todoId={1}>
    <SomeAnimation todoId={1}>
      <SomeLayout todoId={1}>
        <SomeOtherAnimation todoId={1}>
          <SomeDebugContainer todoId={1}>
            <TodoHeader todoId={1}>
            <TodoBody todoId={1}>
              <TodoDetails todoId={1}>
                <TodoStatus todoId={1}> // yay!

在这一点上,我认为这正是 React 上下文的优势所在,因此可能没有特定于 Redux 的模式,但我想错了!

Connect 似乎不是个好主意,正如您所说,每个 Todo 都是一个表示组件,应该忽略任何关于 redux 存储或应用程序的内容。

我在一个项目上遇到了同样的问题,目前我觉得它看起来很痛苦但是它使每个元素都可以重用并简化代码(不是代码量而是逻辑)。也许你可以简化你的 dom/component 结构,使用反应子封装来限制 "levels"

的数量

不确定我帮了多少忙。如果您找到了一个很好的解决方案,我会很高兴阅读它。

祝你好运

为什么他们都需要接受id作为参数?

通常,层次结构中较高的某些组件(例如 Todo)会接受 idtodo,但下面的组件会更具体地接受什么,例如

function Todo({ todo }) {
  return (
     <SomeAnimation>
        <SomeLayout>
          <SomeOtherAnimation>
            <SomeDebugContainer>
              <TodoHeader title={todo.title} />
              <TodoBody {...todo} />
            </SomeDebugContainer>
          </SomeOtherAnimation>
        </SomeLayout>
     </SomeAnimation>
  )
}

在这个例子中,TodoHeader 只是直接接收了一个 title 道具。如果它需要更多道具,您可以像我在 <TodoBody> 中那样使用 {...todo} 分布在 todo 个属性上。从您的示例中看不出为什么像 SomeAnimation 这样的组件也需要知道待办事项 ID——大概传递它的一些视觉属性就足够了。

类似地,像 TodoBody 这样的内部组件可能会将它们的一些 props 向下传递,但同样,这不一定是 ID:

function TodoBody({ title, text, status }) {
  return (
    <div>
      <TodoDetails text={text} />
      <TodoStatus status={status} />
    </div>
  )
}

一般来说,从 render() 返回的树很深通常意味着您的组件结构不是最优的。您不必在每个组件中都使用 this.props.children——随意让组件控制它们自己的渲染,并且只传递它们需要的东西。有时传递 id 很方便,有时直接传递数据会使依赖关系更加明确。