高阶组件和包装元素的访问子元素
Higher-Order Component and accessing child of the wrapped element
React 的新手,我遇到了这个问题,我的两个组件非常相似,但差异很大以至于不一样。
我查找了一种组合组件并避免重复的方法,在 Mixins
的情况下,我遇到了 HOC,我认为它非常强大,但对于像我这样不了解的人来说却很困惑但熟悉 React 及其内部工作原理。
所以我有我的主要组件(wrappee),然后将被包装。反过来,该组件呈现一个子组件(在我的例子中,textarea
用于 wrappee 组件之一,另一个是 input
字段)。
我想使用 HOC 的原因之一是我将事件侦听器绑定到文本输入,因此需要能够从 HOC 访问它。
Textarea ---- InputController ---- InputHOC
Input ---/
在实践中,我设法使用 ref
中的回调将 DOM 元素传回 HOC。但我觉得它很脏,因为我必须有 2 个回调:
InputController
:
return (
<div>
{textareaHint}
<div className='longtext-input-wrapper'>
{textareaComponent}
</div>
</div>
)
textareaComponent
return <TextareaAutosize
ref = {
(c) => {
this._input = c
}
}
className={classList}
minRows={MIN_ROWS}
/>
然后在 InputHOC
:
<div className={submitButtonClass}>
<Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
<span className='button-text'>Ok</span>
<span className='button-icon'>✔</span>
</Button>
<InputComponent ref={
(item) => {
if (item && !this.input) {
this.input = item._input
}
}
}
/>
</div>
然后我可以在 componentDidMount
中访问 this.input
:
const inputNode = ReactDOM.findDOMNode(this.input)
确实感觉很hacky,所以我想知道是否有更好的方法来处理这个问题?
非常感谢您的意见
@Jordan 说的对,这不是用 HOC 模式。可以在此处找到此模式的一个很好的示例:https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775。您可以将 HOC 视为它包装的组件的 superclass,但它实际上并不是 class。 HOC 是一个函数,它接受一个 React 组件和 returns 一个具有所需增强功能的新组件。
你正在做的是使用 ref
回调来 link 你所有的组件,并让其他组件知道除了它们的直接子组件之外的事情,这绝对不推荐。对于您的情况,我不明白为什么您不应该将 InputHOC
中的所有内容都放入 InputController
中。然后,在 InputController
中定义要绑定到 TextareaAutosize
中的输入的函数,并将它们作为 props 传递。它看起来像这样:
输入控制器:
class InputController extends React.Component {
handleChange() {
// Note that 'this' will not be set to the InputController element
// unless you bind it manually
doSomething();
}
render() {
return (
<Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
<span className='button-text'>Ok</span>
<span className='button-icon'>✔</span>
</Button>
<div>
{textareaHint}
<div className='longtext-input-wrapper'>
<TextareaAutosize callback={this.handleChange} />
</div>
</div>
);
}
}
TextareaAutosize
class TextAreaAutosize extends React.Component {
render() {
return (
<textarea onChange={this.props.onChange}>
Some text value
</textarea>
)
}
}
React 的新手,我遇到了这个问题,我的两个组件非常相似,但差异很大以至于不一样。
我查找了一种组合组件并避免重复的方法,在 Mixins
的情况下,我遇到了 HOC,我认为它非常强大,但对于像我这样不了解的人来说却很困惑但熟悉 React 及其内部工作原理。
所以我有我的主要组件(wrappee),然后将被包装。反过来,该组件呈现一个子组件(在我的例子中,textarea
用于 wrappee 组件之一,另一个是 input
字段)。
我想使用 HOC 的原因之一是我将事件侦听器绑定到文本输入,因此需要能够从 HOC 访问它。
Textarea ---- InputController ---- InputHOC
Input ---/
在实践中,我设法使用 ref
中的回调将 DOM 元素传回 HOC。但我觉得它很脏,因为我必须有 2 个回调:
InputController
:
return (
<div>
{textareaHint}
<div className='longtext-input-wrapper'>
{textareaComponent}
</div>
</div>
)
textareaComponent
return <TextareaAutosize
ref = {
(c) => {
this._input = c
}
}
className={classList}
minRows={MIN_ROWS}
/>
然后在 InputHOC
:
<div className={submitButtonClass}>
<Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
<span className='button-text'>Ok</span>
<span className='button-icon'>✔</span>
</Button>
<InputComponent ref={
(item) => {
if (item && !this.input) {
this.input = item._input
}
}
}
/>
</div>
然后我可以在 componentDidMount
中访问 this.input
:
const inputNode = ReactDOM.findDOMNode(this.input)
确实感觉很hacky,所以我想知道是否有更好的方法来处理这个问题?
非常感谢您的意见
@Jordan 说的对,这不是用 HOC 模式。可以在此处找到此模式的一个很好的示例:https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775。您可以将 HOC 视为它包装的组件的 superclass,但它实际上并不是 class。 HOC 是一个函数,它接受一个 React 组件和 returns 一个具有所需增强功能的新组件。
你正在做的是使用 ref
回调来 link 你所有的组件,并让其他组件知道除了它们的直接子组件之外的事情,这绝对不推荐。对于您的情况,我不明白为什么您不应该将 InputHOC
中的所有内容都放入 InputController
中。然后,在 InputController
中定义要绑定到 TextareaAutosize
中的输入的函数,并将它们作为 props 传递。它看起来像这样:
输入控制器:
class InputController extends React.Component {
handleChange() {
// Note that 'this' will not be set to the InputController element
// unless you bind it manually
doSomething();
}
render() {
return (
<Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
<span className='button-text'>Ok</span>
<span className='button-icon'>✔</span>
</Button>
<div>
{textareaHint}
<div className='longtext-input-wrapper'>
<TextareaAutosize callback={this.handleChange} />
</div>
</div>
);
}
}
TextareaAutosize
class TextAreaAutosize extends React.Component {
render() {
return (
<textarea onChange={this.props.onChange}>
Some text value
</textarea>
)
}
}