我的组件视图如下所示。 DataList有多个DataItems,每个DataItem都有一个Header和Body,Header又有一个Expandable部分,带有一个按钮,用于切换相应DataItem的Body的可见性。
DataItem,Header,Expandable,Body是独立的组件,每当点击可扩展按钮时,我都可以通过/解除可扩展的'状态一直到Header& DataItem将一个css类添加到DataItem以显示/隐藏Body部分。
因此,与Expandable一起,即使Header和DataItem也应该可以扩展'状态是多余的,并在组件之间产生紧密耦合。
有没有办法保持公共状态(在MVC中称为Model),可以在ReactJS中的组件中重复使用?
DataList
|
|-DataItem-1
| |
| |-Header
| | |
| | |-Expandable
| |
| |-Body
|
|-DataItem-2
| |
|-Header
| |
| |-Expandable
|
|-Body
答案 0 :(得分:1)
实际上,您不需要向DataItem添加css类来显示/隐藏Body部分。您可以使用React's Conditional Rendering实现此目的。
<强> DataItem.js 强>
import Expandable from './Header';
import Body from './Body';
class DataItem extends React.Component {
constructor(props) {
super(props);
this.state = { showBody: false };
}
onExpandableClick = () => {
this.setState({ showBody: !this.state.showBody });
}
render() {
return (
<div>
<Header onExpandableClick={this.onExpandableClick} {...otherHeaderProps} />
{ this.state.showBody && <Body {...bodyProps} />}
{/* other elements */}
</div>
)
}
}
<强> Header.js 强>
import Expandable from './Expandable';
class Header extends React.Component {
render() {
return (
<div>
<Expandable onClick={this.props.onExpandableClick} />
{/* other elements */}
</div>
)
}
}
<强> Expandable.js 强>
class Expandable extends React.Component {
render() {
return (
<div onClick={this.props.onClick}>
{/* other elements */}
</div>
)
}
}
我们有许多解决方案(状态管理库)来处理我们应用的全局状态。
谈到我最喜欢的Redux,它将整个应用程序的状态保存在单个不可变状态树(对象)中,不能直接更改。当某些内容发生变化时,会创建一个新对象(使用操作和缩减器)。
Redux因其简单,体积小(仅2 KB)和出色的文档而非常受欢迎。正如Redux的作者所说,
&#34; Redux API表面很小。如果删除开发人员警告, 评论和理智检查,它的99行。没有棘手的异步 要调试的代码。&#34;
查找全面的文档here。
答案 1 :(得分:0)
永远不要在多个组件状态下复制相同的状态项。这将导致问题,因为它们总是需要手动保持同步。
在这种情况下,我会将展开的属性定义为DataItem
本身的属性,而不是正文的属性。这允许您将信息保持在DataItem
的状态,并在需要时将其传递下去。不要将信息保留在标题中,而是将回调传递到允许其切换属性的Header
组件中。
这可以类似于下面的代码段实现。运行代码段以查看其实际效果!
class App extends React.Component {
constructor(props) {
super(props)
this.toggleExpand = this.toggleExpand.bind(this)
this.state = {
expanded: true
}
}
toggleExpand() {
this.setState({
expanded: !this.state.expanded
})
}
render() {
return (
<div>
<Header toggleExpand={this.toggleExpand} />
<Body expanded={this.state.expanded} />
</div>
)
}
}
const Header = props => (
<div id='header'>
<button onClick={props.toggleExpand}>
Toggle Expand
</button>
</div>
)
const Body = props => (
props.expanded ?
<div id='body'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
: null
)
ReactDOM.render(
<App />,
document.getElementById('app')
)
#header, #body {
border: 1px solid black;
padding: 5px;
margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>