有人可以解释一下 React 中的高阶组件吗?我已经阅读并重新阅读了文档,但似乎无法更好地理解。根据文档,HOC 通过创建一个返回反应组件的主函数,通过将参数传递给该函数来帮助消除重复。我有几个问题。
Button或EnhancedButton。我尝试创建一个这样的 HOC:
// createSetup.js
import React from 'react';
export default function createSetup(options) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.testFunction = this.testFunction.bind(this);
}
testFunction() {
console.log("This is a test function");
}
render() {
return <p>{options.name}</p>
}
}
}
// main.js
import React from 'react';
import {render} from 'react-dom';
import createSetup from './createSetup';
render((<div>{() => createSetup({name: 'name'})}</div>),
document.getElementById('root'););
Run Code Online (Sandbox Code Playgroud)运行这个不会显示 HOC,只显示 div
任何人都可以提供比给出的更好的例子吗?
我正在使用airbnb配置进行eslint,它给了我这个警告:
[eslint] 'isLoading' is missing in props validation (react/prop-types)
有没有办法为isLoading设置PropTypes?
const withLoading = Component => ({ isLoading, ...rest }) =>
(isLoading ? <LoadingSpinner /> : <Component {...rest} />);
Run Code Online (Sandbox Code Playgroud)
这是我如何使用它的一个例子:
const Button = ({ onClick, className, children }) => (
<button onClick={onClick} className={className} type="button">
{children}
</button>
);
Button.propTypes = {
onClick: PropTypes.func.isRequired,
className: PropTypes.string,
children: PropTypes.node.isRequired,
};
Button.defaultProps = {
onClick: () => {},
className: '',
children: 'Click me',
};
const Loading = () => (
<div>
<p>Loading...</p>
</div>
);
const …Run Code Online (Sandbox Code Playgroud) reactjs eslint react-proptypes higher-order-components eslint-config-airbnb
我正在创建高阶组件,用于通过另一个组件传递一些道具。但是收到未知事件处理程序属性的警告。
export class TableHeaderRow extends React.PureComponent{
render() {
const customCell = WrappedCellComponent(Cell,this.props.onHeaderClick, this.props.isMasterChecked, this.props.onTableCheckBoxselection);
return (
<TableHeaderRowBase
cellComponent={customCell}
rowComponent={Row}
contentComponent={Content}
titleComponent={Title}
showSortingControls={true}
sortLabelComponent={this.props.sortLabelComponent}
groupButtonComponent={(data: any) : any => null}
showGroupingControls={false}
{...this.props}
/>
)
}
}
const WrappedCellComponent = (WrappedComponent, onHeaderClick,checkIfMasterChecked, onTableCheckBoxSelection) => {
class HOC extends React.Component {
render() {
return <WrappedComponent
{...this.props}
onHeaderClick={onHeaderClick}
onTableCheckBoxSelection={onTableCheckBoxSelection}
checkIfMasterChecked={checkIfMasterChecked}
/>;
}
}
return HOC;
};
Run Code Online (Sandbox Code Playgroud)
事件正在运行,但我在 chrome devTool 中遇到错误(即警告:未知事件处理程序属性onTableCheckBoxSelection。它将被忽略。)
我正在尝试从头开始学习 React 并对概念有深入的了解!
今天我在搜索 HOC、Render Props 以及两者之间的差异。我已经检查了两者的渲染时间。我写了一个console.log('rendered')into 渲染来检查浏览器控制台中的渲染时间。
HOC:当我使用 HOC 编写一个可用的组件时,我会在每次更改道具后看到我为 HOC 和使用 HOC 的组件渲染。
渲染道具:在这种情况下,我改变了道具,但只有包装器组件已经渲染。因为使用渲染道具我们只加载一个组件并注入代码以使用该组件功能!
那么,使用 Render Props 而不是 HOC 组件有好处吗?或者 HOC 组件可用且功能强大吗?
谢谢
以下是高阶组件.HOC专门连接到redux以访问其中一个动作创建者:importantReduxAction.
function withExtraStuff (InnerComponent) {
return class Enhancer extends React.Component {
constructor(props){
super(props)
this.importantMethod = this.importantMethod.bind(this)
}
importantMethod(){
//try to call the higher order component's action creator
this.props.importantReduxAction()
}
render(){
return <InnerComponent
{...this.props}
importantMethod={this.importantMethod}
/>
}
}
let mapDispatchToProps = (dispatch)=>{
return bindActionCreators({importantReduxAction}, dispatch)
}
return connect(null, mapDispatchToProps, null, {pure: false})(Enhancer)
}
Run Code Online (Sandbox Code Playgroud)
这是将使用HOC组件的包装组件.它还将自身连接到redux以获得对不同方法的访问:otherReduxAction.
class ChildComponent extends React.Component {
constructor(props){
super(props)
this.doImportantThing = this.doImportantThing.bind(this)
}
doImportantThing(){
//try to call the higher order component's method (this is where …Run Code Online (Sandbox Code Playgroud) component composition官方 react.js 上的教程描述了如何使用组合来避免继承,并且在大多数情况下我看到了这里的优势。
但是网站也提到了we haven’t found any use cases where we would recommend creating component inheritance hierarchies
src:https : //reactjs.org/docs/composition-vs-inheritance.html
但是我们有一个关于 HOC(高阶组件)模式
src的教程:https : //reactjs.org/docs/higher-order-components.html
它建议编写用于生成复合组件的函数,以避免重复逻辑。
此模式也用于 Relay 中,用于与 GraphQL 配合使用的组件。
对于来自 C#/Java/PHP 背景的人来说,他们的 HOC 用例看起来像是何时使用继承的明显例子。这是我之前在 React 中自己做的,发现它非常直观,更重要的是易于调试。
我也在努力理解 HOC 中使用的生成器函数相对于常规复合组件的优势,后者通过 props 获取内部组件。
所以我的问题是:React 中的 HOC 是否存在无法通过组合或继承轻松解决的用例?
示例将不胜感激。
更新:发现这篇文章Inheritance Inversion建议让您的包装类从您的内部类继承并调用它的 render() 方法。
我可能有偏见,所以我不会立即放弃这个想法,因为它可能有实际用途,但我必须首先对其进行更多研究。
如果您知道这何时可以击败常规组合或继承,请发表评论,或者如果您认为自己有一个很好的案例,请留下一个答案。
我有一个通用的React组件,像这样说:
class Foo<T> extends React.Component<FooProps<T>, FooState> {
constructor(props: FooProps<T>) {
super(props);
render() {
return <p> The result is {SomeGenericFunction<T>()}</p>;
}
}
Run Code Online (Sandbox Code Playgroud)
我也有一个看起来与此类似的HOC(但没有意义):
export const withTd =
<T extends WithTdProps>(TableElement: React.ComponentType<T>): React.SFC<T> =>
(props: T) => <td><TableElement {...props}/></td>;
Run Code Online (Sandbox Code Playgroud)
但是当我使用这样的组件时:
const FooWithTd = withTd(Foo);
Run Code Online (Sandbox Code Playgroud)
没有方法可以传递类型参数,因为您既不能withTd(Foo<T>)也不可以做FooWithTd,则类型总是错误的。这样做的正确方法是什么?
编辑:问题是我希望<FooWithTd<number> {...someprops}/>以后能有类似的东西,因为我T在HOC中不知道所需的类型。
我一直在研究高阶组件的反应.我的要求是我有一个集合组件,我需要扩展它们,以便在不重写整个组件的情况下为它们提供更多功能.在这种情况下,我发现了HOC中的概念,其中可以使用纯函数扩展组件.我的问题是,我可以将扩展组件导出为普通组件.举个例子
需要扩展的组件
class foo extends React.Component {
render(){
//something
}
}
export default foo;
Run Code Online (Sandbox Code Playgroud)
HOC组件
function bar(foo) {
render() {
return <foo {...this.props} {...this.state} />;
}
}
export default bar;
Run Code Online (Sandbox Code Playgroud)
我能用这种方式组件吗?或者我做错了吗?
我经常使用HOC为现有的React组件提供附加功能,这非常简单:
import Component from '/path/to/Component';
import higherOrderComponent from '/path/to/higherOrderComponent';
const EnhancedComponent = higherOrderComponent(Component);
Run Code Online (Sandbox Code Playgroud)
但是,我需要包装一个简单的HTML input,它不作为独立的React组件存在。我试过了
const EnhancedInput = higherOrderComponent(<input />);
Run Code Online (Sandbox Code Playgroud)
并得到以下错误:
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Run Code Online (Sandbox Code Playgroud)
如何正确传递输入?
我正在使用 Jest 为我的 React Native 应用程序编写单元测试。我有一个组件,它被包裹在withNavigationHOC 中。
我的问题是我的测试崩溃,抛出:
? LoginScreen component › given no props: should render a login form
Invariant Violation: withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.
Run Code Online (Sandbox Code Playgroud)
我正在使用@testing-library/react-native我的测试,我设置了一个自定义渲染方法,如下所示:
import { render } from '@testing-library/react-native';
import React from 'react';
import { NavigationContext } from 'react-navigation';
import { Provider } from 'react-redux';
import store from …Run Code Online (Sandbox Code Playgroud) jestjs react-native higher-order-components react-navigation react-testing-library
reactjs ×9
javascript ×4
components ×1
ecmascript-6 ×1
es6-class ×1
eslint ×1
generics ×1
jestjs ×1
jsx ×1
react-hooks ×1
react-native ×1
react-redux ×1
redux ×1
typescript ×1