在相邻组件之间共享内容,HOC? [英] Sharing content between adjacent components, HOC?

查看:46
本文介绍了在相邻组件之间共享内容,HOC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个容器组件,该组件在其中渲染了两个组件.根据容器中的某些道具,顶部组件可以更改,但下部组件将始终保持不变.

I have a container component which renders two components inside it. Depending on some props in the container, the top component can change, but the lower component will always remain the same.

我想在较低的组件内部内部渲染一些附加的内容(DOM元素/其他React组件),但是附加的内容是在顶部的组件内部创建的.我正在努力弄清楚在这里需要重构什么才能完成这项工作.我最初尝试将创建的内容传递到容器,然后再传递到较低的组件.我很快意识到这是行不通的,因为创建的内容依赖于创建它的组件的props/state.

I want to render some additional content (DOM elements/other react components) inside the lower component, but the additional content is created inside the top component. I'm struggling to figure out what I need to refactor here to make this work. I initially tried passing the created content up to the container, and then back down to the lower component. I soon realised this doesn't work because the created content relies on the props/state of the component that created it.

在容器内创建内容是不可行的,因为可以创建哪些内容的选择太多了.我正在研究的代码库有30-40个可能的组件,它们都会生成不同的内容.

Creating the content inside the container isn't feasible because there are so many different options for what content can be created. The codebase I'm working on has 30-40 possible components which all generate different content.

我对React还是很陌生,所以我很难尝试以React的方式解决这个问题.我已经简要阅读了有关渲染道具/HOC的信息,也许那是我在这里需要的?任何帮助将不胜感激.

I'm fairly new to React so I'm having difficulty trying to solve this the react way. I've read briefly about render props/HOCs, maybe thats what I need here? Any help would be greatly appreciated.

这是一个非常基本的示例: https://codesandbox.io/s/zqo2p1yy9m

Here is a very basic example of what it looks like: https://codesandbox.io/s/zqo2p1yy9m

推荐答案

有两种方法可以解决此问题

There are a couple of ways to approach this issue

1)您可以使用状态管理系统(例如Redux,mobx),也可以使用React的上下文API https://reactjs.org/docs/context.html .但是,由于您对React还是比较陌生,所以我建议您在熟悉基本流程之前不要使用这些正确的知识来解决

1) You can use state management system such as Redux, mobx or you can use React's context API https://reactjs.org/docs/context.html. HOWEVER, since you are fairly new to React, I would suggest not tackle with these right know till you are comfortable with the basic flow

2)您可以实现简单的父子关系在组件之间传递数据.最终,这使您可以在相邻(同级)组件之间提供通信.如前所述,该流程通常称为提升状态.实际上,状态管理系统以类似的方式工作.让我通过考虑基于场景的代码示例来解释这种逻辑.

2) You can implement a simple parent-child relationship to pass data between components. Eventually, this allow you to provide a communication between adjacent(sibling) components. As it's already stated, that flow is generally called lifting up the state. Actually, state management systems works in a similar way. Let me explain this logic by also taking your scenario based code sample into account.

我们将有一个容器组件.该组件将是有状态组件.此Container组件的唯一目的是使其具有自己的整体状态,该状态将被其子级视为真理的来源.有两种方法来定义更新此整体状态的方法.子组件将是纯组件或代表性组件.这意味着,他们将没有自己的状态.它们要么用于显示其父级传递给他们的数据,要么用于触发由其父级定义的方法,以更新真相状态的来源.

We'll have a Container component. This component will be a stateful component. The sole purpose of this Container component is having it's own holistic state, that will be treated as the source of truth by its children. Having a couple of methods to define ways to update this holistic state. The children components will be pure components, or representational components. That means, they will not have their own states. They will either be used to show data that their parent passes to them or trigger methods that are defined by their parent in order to update source of truth state.

我们将有两种情况:在方案1中,内容列表将按原样表示.在方案2中,内容列表将通过颠倒字母顺序来表示

We'll have two scenarios: In scenario 1, the list of content will be represented as it is. In scenario 2, the list of content will be represented by reversing the order of letters

class Container extends React.PureComponent {
  state = {
    reversed: false,
    newContent: "",
    contents: [
      {
        id: 1,
        text: "Initial Content"
      }
    ]
  };

  handleReverse = () => {
    this.setState((state) => ({
      ...state,
      reversed: !state.reversed
    }))
  }
  submitNewContent = () => {
    this.setState(state => ({
      ...state,
      contents: [
        ...state.contents,
        { id: Math.random(), text: state.newContent }
      ],
      newContent: ""
    }));
  };
  addNewContent = content => {
    this.setState({ newContent: content });
  };

  render() {
    return (
      <React.Fragment>
        <ContentCreator
        value={this.state.newContent}
        handleChange={this.addNewContent}
        handleClick={this.submitNewContent}
        />
        {this.state.reversed ? <ReversedContentDisplayer contents={this.state.contents} /> : <ContentDisplayer contents={this.state.contents} />}
        <Reversifier reversed={this.state.reversed} handleReverse={this.handleReverse}/>
      </React.Fragment>
    );
  }
}

如您所见,容器仅具有状态,一些用于更新状态和子组件的方法.在其render方法内部未使用任何html.

As you can see, the container only has a state, some methods to update the state and child component. Not a single html used inside of its render method.

我们的第一个子组件是 ContentCreator

Our first child component is ContentCreator

function ContentCreator({
  handleChange,
  handleClick,
  value
  }) {
  return (
    <div className="App">
      <label> New Content</label>
      <input type="text" value={value} onChange={event => handleChange(event.target.value)} />
      <button onClick={handleClick}>Add Content</button>
    </div>
  );
}

这个组件的行为就像一个表单(我很懒,实际上是用form和onSubmit函数包装它的).这个组件的主要目的是更新我们真实状态源的 contents

This component acts like a form (I'm to lazy to actually wrap it with form and onSubmit function). And the main purpose of this component is to update the contents key of our source of truth state

第二个组件称为 Reversifier (虽然我不相信有这个词)

The second component is called Reversifier (I don't believe there is such a word though)

function Reversifier({reversed, handleReverse}) {
  return <button onClick={handleReverse}>{reversed ? 'Back to normal' : 'Reversify'}</button>
}

此组件的主要目的是切换真实状态源的 reversed 键.您还可以看到,基于 reversed 的值,按钮内的文本也会发生变化(以不同的方式反映出不同的情况)

The main purpose of this component is to toggle reversed key of our source of truth state. You can also see that, based on the value of reversed the text inside of the button also changes (reflects sort of different scenarios in a different way)

最后两个组成部分是

function ContentCreator({
  handleChange,
  handleClick,
  value
  }) {
  return (
    <div className="App">
      <label> New Content</label>
      <input type="text" value={value} onChange={event => handleChange(event.target.value)} />
      <button onClick={handleClick}>Add Content</button>
    </div>
  );
}

function ReversedContentDisplayer({ contents }) {
  return (
    <div className="App">
      {contents.map(content => (
        <div key={content.id}>{content.text.split("").reverse().join("")}</div>
      ))}
    </div>
  );
}

基于场景,即在容器组件的render方法内部还是以常规或反向显示内容,我们将显示其中一个.实际上,这两个组件可以写成一个,例如

Based on the scenario, that is whether display content as regular or reversed, inside or our container component's render method, we display either of them. Actually, these two components can be written as one such as

function ContentDisplayer({ contents, reversed }) {
  return (
    <div className="App">
      {contents.map(content => (
        <div key={content.id}>{reversed ? content.text.split("").reverse().join("") : content.text}</div>
      ))}
    </div>
  );
}

但是为了反映不同的情况,我创建了两个不同的组件

But in order to reflect different scenarios, I created two distinct components

我为您创建了一个codeandbox,以防您想使用该功能而看到最终结果 https://codesandbox.io/s/04rowq150

I created a codesandbox for you in case you want to play with the functionality yo see the end result https://codesandbox.io/s/04rowq150

因此,通过这种方式,您不必在 Container 内创建任何内容,而是可以通过定义初始状态和几种方法来传递其子代,以允许他们创建新内容,并代表 Container

So by this way, you don't have to create any content inside of the Container, rather you can use Container as a guideline by defining initial state and a couple of methods to pass its children to allow them creating new contents, and displaying these newly created contents on behalf of the Container

我希望该示例可以为您提供一个起点,并且希望我至少理解51%的要求.如果您还有其他疑问或困惑,请告诉我

I hope this sample helps you as a starting point and I hope that I understand your requirement at least 51% right. If you have further questions or confusions, please let me know

这篇关于在相邻组件之间共享内容,HOC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆