有几种方法可以解决这个问题
1) 您可以使用 Redux、mobx 等状态管理系统,也可以使用 React 的上下文 API https://reactjs.org/docs/context.html。但是,由于您对 React 相当陌生,因此我建议您在熟悉基本流程之前不要使用这些正确的知识
2)您可以实现一个简单的parent-child relationship
组件之间传递数据。最终,这允许您提供相邻(兄弟)组件之间的通信。如前所述,该流程通常称为提升状态。实际上,状态管理系统以类似的方式工作。让我通过考虑您的基于场景的代码示例来解释这个逻辑。
我们将有一个 Container 组件。这个组件将是一个有状态的组件。这个 Container 组件的唯一目的是拥有它自己的整体状态,它将被它的孩子视为真相的来源。有几种方法可以定义更新这种整体状态的方法。子组件将是纯组件或代表性组件。这意味着,他们不会有自己的状态。它们将用于显示其父级传递给它们的数据或触发其父级定义的方法以更新真实状态的来源。
我们将有两种方案: 在方案 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 函数实际包装它)。而这个组件的主要目的是更新contents
我们真实状态源的key
第二个组件被称为Reversifier
(虽然我不相信有这样的词)
function Reversifier({reversed, handleReverse}) {
return <button onClick={handleReverse}>{reversed ? 'Back to normal' : 'Reversify'}</button>
}
该组件的主要目的是切换reversed
我们真实状态来源的键。您还可以看到,基于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>
);
}
但是为了反映不同的场景,我创建了两个不同的组件
我为您创建了一个代码沙箱,以防您想使用该功能,您会看到最终结果https://codesandbox.io/s/04rowq150
因此,通过这种方式,您不必在 内部创建任何内容Container
,而是可以Container
通过定义初始状态和一些方法来传递其子项以允许他们创建新内容并显示这些新创建的内容来用作指导内容代表Container
我希望这个示例可以帮助您作为起点,并且我希望我至少 51% 正确理解您的要求。如果您有进一步的问题或困惑,请告诉我