我有一个容器组件,其中呈现两个组件。根据容器中的某些道具,顶部组件可以更改,但下部组件将始终保持不变。
我想在较低的组件中呈现一些额外的内容(DOM元素/其他反应组件),但是额外的内容是在顶部组件中创建的。我正在努力弄清楚我需要在这里重构什么来完成这项工作。我最初尝试将创建的内容向上传递到容器,然后返回到较低的组件。我很快意识到这是行不通的,因为创建的内容依赖于创建它的组件的道具/状态。
在容器中创建内容是不可行的,因为可以创建哪些内容有很多不同的选项。我正在研究的代码库有30-40个可能的组件,它们都生成不同的内容。
我对反应相当陌生,所以我很难用反应的方式解决这个问题。我已经简要地阅读了渲染道具/HOCs,也许这就是我在这里需要的?任何帮助将不胜感激。
下面是一个非常基本的例子:https://codesandbox.io/s/zqo2p1yy9m
有几种方法可以解决这个问题
1) 您可以使用状态管理系统,如Redux、mobx,也可以使用React的上下文APIhttps://reactjs.org/docs/context.html.然而,由于您对反应还比较陌生,我建议在您熟悉基本流程之前不要使用这些正确的“知道”
2) 您可以实现一个简单的父子关系
,以便在组件之间传递数据。最终,这允许您在相邻(同级)组件之间提供通信。如前所述,该流通常称为提升状态。实际上,国家管理系统的工作方式与此类似。让我通过考虑基于场景的代码示例来解释这个逻辑。
我们将有一个容器组件。该组件将是有状态组件。这个容器组件的唯一目的是拥有它自己的整体状态,这将被它的子元素视为真理的来源。有几个方法来定义更新这种整体状态的方法。子组件将是纯组件或表示组件。也就是说,他们不会有自己的国家。它们要么用于显示其父级传递给它们的数据,要么触发其父级定义的方法,以更新真相状态的来源。
我们将有两个场景:在场景1中,内容列表将按原样表示。在场景2中,内容列表将通过颠倒字母顺序来表示
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>
);
}
}
如您所见,容器只有一个状态,一些更新状态和子组件的方法。在其渲染方法中没有使用任何html。
我们的第一个子组件是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>
);
}
这个组件的行为就像一个表单(我懒得用表单和onSubmit函数来包装它)。该组件的主要目的是更新真理之源状态的内容
键
第二个组件叫做反向器
(不过我不相信有这样一个词)
function Reversifier({reversed, handleReverse}) {
return <button onClick={handleReverse}>{reversed ? 'Back to normal' : 'Reversify'}</button>
}
此组件的主要目的是切换真实源状态的反向
键。您还可以看到,根据reversed
的值,按钮内部的文本也会发生变化(以不同的方式反映不同的场景)
最后两个部分是
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>
);
}
根据场景,即在容器组件的渲染方法内部或容器组件的渲染方法中,是否将内容显示为常规内容或反转内容,我们将显示其中任何一种。实际上,这两个组件可以写成一个,比如
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>
);
}
但为了反映不同的场景,我创建了两个不同的组件
我为您创建了一个codesandbox,以防您想使用它的功能看到最终结果https://codesandbox.io/s/04rowq150
因此,通过这种方式,您不必在容器
内创建任何内容,而是可以使用容器
作为指导原则,通过定义初始状态和几个方法传递其子级以允许它们创建新内容,并代表容器显示这些新创建的内容
我希望这个例子能帮助你作为一个起点,我希望我理解你的要求至少51%的权利。如果您有进一步的问题或困惑请让我知道
react的性质是自上而下的。所以,如果您需要共享一部分状态或一些数据作为道具传递,则需要将该代码提升到其父级。将Jsx作为道具传递是很好的,在这里您需要这样做,并且您可以这样做。
更多信息:提升状态
——————
A.
/ \
公元前
所以,如果你在B和C之间共享了代码,你可以把它提升到A,然后作为道具传递给B和C。如果需要从B到C的状态,则将状态提升到A。如果需要从A到B或C的状态进行访问和修改,则只需将函数作为回调传递给B或C即可
我同意维克托的观点。是的,但我想知道你们是否有像redux这样的全球商店。然后,您可以调用操作,从顶部组件更新存储的状态。高阶组件可以接收存储状态作为道具,并更新低阶组件。