【发布时间】:2018-11-13 10:48:17
【问题描述】:
我正在开发一个 UI 库,我的一些组件会根据用户的一些交互来改变它们的“状态”。
例如,用户单击手风琴面板的标题会导致手风琴面板打开并变得可见。这种状态是通过将visible 修饰符添加到手风琴面板来实现的,如下所示。:
<div class="accordion">
<div class="accordion_panel-visible">
<div class="accordion_title">foo</div>
<div class="accordion_content">bar</div>
</div>
<div class="accordion_panel">
<div class="accordion_title">fizz</div>
<div class="accordion_content">buzz</div>
</div>
</div>
我之前的假设是 React State 应该用于根据一些后端数据重新渲染组件。但是,基于查看其他 UI 库等的源代码,它们似乎也在使用 React State 处理 UI 状态。
所以使用 React,我可以通过使用原始 DOM API 来实现我想要的(如这里的示例所示 - https://reactjs.org/docs/refs-and-the-dom.html):
Accordion.defaultProps = {
name: 'accordion'
};
class Accordion extends React.Component {
toggle(event) {
const panel = event.target.closest('[data-component="panel"]');
const operator = panel.modifier('active') ? 'unset' : 'set';
panel.modifier('active', operator);
}
render() {
return (
<Module {...this.props}>
{this.props.panels.map(({ title, content }, index) => (
<Component name='panel' key={index}>
<Component name='title' onClick={this.toggle}>{title}</Component>
<Component name='content'>{content}</Component>
</Component>
))}
</Module>
)
}
}
这一切都很好——但我本质上是从一个 React 组件中进行 DOM 操作,我经常阅读应该避免。在这种情况下,我应该使用 React State 和 Refs(而不是直接的 DOM 操作)。为了实现与上述相同的目标,我相信我可以做到:
Accordion.defaultProps = {
name: 'accordion'
};
class Accordion extends React.Component {
constructor(props) {
super(props);
this.panels = [];
this.state = { activePanel: null };
}
toggle(index) {
this.setState({
activePanel: (this.panels[index] === this.state.activePanel) ? null : this.panels[index]
});
}
isActive(index) {
return (this.panels[index] === this.state.activePanel) ? true : false;
}
render() {
return (
<Module {...this.props}>
{this.props.panels.map(({ title, content }, index) => (
<Component name='panel'
key={index}
ref={ref => this.panels[index] = ref}
modifiers={this.isActive(index) ? 'active' : false}
>
<Component name='title' onClick={this.toggle.bind(this, index)}>
{title}
</Component>
<Component name='content'>{content}</Component>
</Component>
))}
</Module>
)
}
}
(我知道上面的 sn-p 的行为会关闭同级面板,这不是第一个 sn-p 的情况,但这是微不足道的,可以忽略)。
所以我的问题是,我是否应该为此使用 React State(即后一个示例)?
感觉就像我的应用正在显示/隐藏/打开/关闭基于 用户交互 的 UI 元素,这些元素不需要/修改/发布/更新/获取/接收任何方式的数据,那么 React 不应该真正关心它们。
但最重要的是 - 这取决于偏好 吗?是否应该由 me 来决定 React 是否应该关心这个?归根结底,React 是一个工具,我目前正在使用该工具在后端免费环境中创建和渲染 UI 组件。我现在真的很困惑,不确定我是否真的能看到在这种情况下使用 state 的好处。
谢谢!
【问题讨论】:
-
通常直接 dom 操作不是一个好主意,如果它是一个反应组件正在使用的东西,除非该项目与组件没有相关性(这意味着如果你只是想从你可以抓住的东西中获取价值它通过 DOM 而不是使用 ref.. 等)。也就是说,通常当组件需要切换不与任何其他组件共享的视图时,您会使用状态。如果它是多个组件所需的变量,则应将其移至某个商店。
-
另外,如果某些操作是繁重的操作(例如
requestAnimationFrame,您正在为某物制作动画或渲染画布,您在鼠标移动时绘制某物......这不需要状态,您将不需要组件生命周期,只需画布或直接 dom 操作)。所以我想这个故事的寓意是状态是一个非常有用的工具,但具体取决于用例。如果它是一个繁重的操作,你可能可以避免状态,如果它是多个组件需要的东西,那么可能又想使用一个商店。 state 有利于本地操作 -
感谢@JohnRuddell - 有用且有见地。听起来我应该在我的上下文中使用状态。但是,问题仍然在于为什么,除了为了它,因为“这是正确的 React 方式”——在我分享的示例中,React State 方式需要更多代码并且可读性较差,至少对我来说。但我想确保我了解全部情况,包括我尚未考虑的事情。
-
好吧,如果你不使用 state 并直接改变 dom,那么使用 react 有什么意义。 React 不再知道任何元素中的内容,这使得它变得毫无意义。您可以利用 JS 内存中元素的强大功能。老实说,虽然我通常避免使用 state,但我的存储使用 redux,如果可能的话,尽量使用功能组件。我用于切换侧边栏的状态等等
-
这里有一些链接供您阅读。 medium.freecodecamp.org/… ... camjackson.net/post/9-things-every-reactjs-beginner-should-know ... engineering.opsgenie.com/… 第一个链接谈到了在 JS 中利用 html 的力量以及你可以用它做什么
标签: reactjs user-interface ref react-state-management