有没有办法可以通过React高阶组件将上下文传递给它包装的组件?
我有一个HOC从其父级接收上下文,并利用该上下文执行基本的通用操作,然后包装一个也需要访问相同上下文以执行操作的子组件.例子:
HOC:
export default function withACoolThing(WrappedComponent) {
return class DoACoolThing extends Component {
static contextTypes = {
actions: PropTypes.object,
}
@autobind
doAThing() {
this.context.actions.doTheThing();
}
render() {
const newProps = {
doAThing: this.doAThing,
};
return (
<WrappedComponent {...this.props} {...newProps} {...this.context} />
);
}
}
};
Run Code Online (Sandbox Code Playgroud)
包裹组件:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { autobind } from 'core-decorators';
import withACoolThing from 'lib/hocs/withACoolThing';
const propTypes = {
doAThing: PropTypes.func,
};
const contextTypes = {
actions: …Run Code Online (Sandbox Code Playgroud) javascript ecmascript-6 reactjs redux higher-order-components
我经常使用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)
如何正确传递输入?
我们正在尝试自定义 HOC 的参数(特别是react-graphql)。由于这个特定库 HOC 的工作方式,我们无法在调用 HOC 后影响组件状态(查询和选项)。
在像connect()Redux这样的传统 HOC 工厂中,所有包含的逻辑都会立即应用——这对我们来说还为时过早。相反,我将原始 HOC ( applyOriginalHOC()) 的应用推迟到从该组件构建第一个实例之前。
export function applyLazyHOC(args) {
return function wrap(WrappedComponent) {
let ComponentWithLazyHOC; // Closed-over value is scoped to component
class LazyHOC extends Component {
constructor() {
super();
// Lazy initialising of HOC to give customisations an opportunity to be registered
if (!ComponentWithLazyHOC) {
ComponentWithLazyHOC = applyOriginalHOC(
// Adds customisations which have been registered by third party code
myCustomization(args)
)(WrappedComponent);
}
}
render() { …Run Code Online (Sandbox Code Playgroud) 我正在使用 React-Router 4 创建一些路由。(它使用官方文档PrivateRoute中的组件,但这与这个问题无关。)
<HashRouter>
<Switch>
<PrivateRoute exact path='/' component={Wrapper(Home)} />
<Route exact path='/login' render={(props) => <Login authenticate={this.authenticate} {...props} />} />
<PrivateRoute exact path='/clients' component={Wrapper(Clients)} />
</Switch>
</HashRouter>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的Home和Clients组件被包装在HOC中。目前这没有任何作用:
const Wrapper = (Page) => {
return (props) => (
<div className="page">
<p>This should be on every page</p>
<Page {...props} />
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
这很好用。我不知道如何将Login路线包装在同一个 HOC 中。我试过了
<Route exact path='/login' render={(props) => Wrapper(<Login authenticate={this.authenticate} {...props} />)} />
Run Code Online (Sandbox Code Playgroud)
但这会返回错误:
Route.render():必须返回有效的 React …
我正在尝试创建一个 HOC,它使常规功能组件 »Touchable«。
所以我有一个这样的 HOC:
const Touchable = (Component, handler) => {
const T = ({props, children}) => {
const Instance = React.createElement(
Component,
{
...props,
onTouchStart: (e) => handler.touchStart(e),
/*more listeners*/
}, children);
}
return T;
}
Run Code Online (Sandbox Code Playgroud)
另一个像这样的组件:
const Button = ({props, children}) => <div>…</div>;
export default Touchable(Button, {touchStart: () => {}});
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
<Button>Hallo</Button>
Run Code Online (Sandbox Code Playgroud)
结果(反应开发人员面板):
<Button onTouchStart={…}>
<div>…</div>
</Button>
Run Code Online (Sandbox Code Playgroud)
但我真正想要的是:
<Button>
<div onTouchStart={…}>…</div>
</Button>
Run Code Online (Sandbox Code Playgroud)
我试图克隆实例,但不知何故我没有运气。我怎样才能做到这一点?
我只是开始使用HOCin React,让我有点困惑的一件事是,在这个例子中我的内部函数如何获得props作为参数的访问权限?
const withProps = Component => (
props => {
return <Component {...props}/>
}
)
export default withProps
Run Code Online (Sandbox Code Playgroud) 我正在使用重组库和 HoC 为我的组件传递一堆 props。我想知道是否有办法compose在设置 HoC 之前检查 props。例如,假设我有这样的东西:
export default compose(
withProps(props => ({
shouldUseWithMyHoc: someCondition() // true or false
})),
withState('someState', 'setSomeState', ''),
withHandlers({
doStuff: props => evt => {
// do stuff
}
}),
withMyHoc() // should only use if `shouldUseWithMyHoc` prop is true
)(MyComponent)
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能withMyHoc仅在shouldUseWithMyHoc设置为 时使用true?
我想过也许可以做一个三元组,但是进展并不顺利,当条件为假时我没有什么可以依靠的。它看起来像这样:
export default compose (
...
(props) => {(
props.shouldUseWithMyHoc
? withMyHoc()
: null)}
)(MyComponent)
Run Code Online (Sandbox Code Playgroud)
通过使用三元,我收到以下错误:
警告:无法在未安装的组件上调用 setState(或forceUpdate)。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请在 componentWillUnmount 方法中取消所有订阅和异步任务。
我有办法完成这件事吗?如果这看起来是正确的,那么我做错了什么?
我有以下内容:
class StyledInput extends React.Component{
styles = (color, theme) => ({
underline: {
borderBottom: `2px solid ${color}`,
'&:after': {
borderBottom: `2px solid ${color}`,
}
}
})
div = props => (
<TextField
placeholder="temp input"
InputProps={{
classes:{
root: props.classes.underline
},
style:{
height: '1.5rem',
fontSize:'1rem',
marginTop: '-1rem',
}
}}
>
<div>
{props.children}
</div>
</TextField>
)
Styled = withStyles(this.styles('white'))(this.div)
render(){
return(
<div>
<this.Styled>{this.props.children}</this.Styled>
</div>
);
}
}
export default StyledInput;
Run Code Online (Sandbox Code Playgroud)
因此,当用户单击该字段时,它会成功获取材质 UI 文本字段并将底部栏更改为白色,而不是蓝色。伟大的!
...然而...
我真正想做的是
<this.Styled color={someDefinedColor}>{this.props.children}</this.Styled>
Run Code Online (Sandbox Code Playgroud)
然后Styled看起来像这样:
Styled = (color) …Run Code Online (Sandbox Code Playgroud) 我有类似于以下的代码:
const HOC = (props, WrappedComponent) => {
return (
<>
<WrappedComponent />
<Icon className="props.iconStyles" />
</>
);
};
Run Code Online (Sandbox Code Playgroud)
这实际上不是有效的代码,但您可以希望看到我正在尝试完成的工作。我希望能够通过以下方式使用它:
<HOC iconStyles="icon-stuff">
<TheComponentIWantToWrap>
</HOC>
Run Code Online (Sandbox Code Playgroud)
我怎样才能正确地写这个,以便能够通过道具?我想我可能也需要在children这里使用,不确定。
profile本质上,我为 Next.js 应用程序中的两个页面(即和)创建了一个 HOC,dashboard两个页面阻止用户在未经授权的情况下访问它们。
例子:pages/profile.js
import withAuth from "../components/AuthCheck/index";
function Profile() {
return (
<>
<h1>Profile</h1>
</>
)
}
export default withAuth(Profile);
Run Code Online (Sandbox Code Playgroud)
我的身份验证组件/HOC:
import { useRouter } from 'next/router'
import { useUser } from '../../lib/hooks'
import { PageLoader } from '../Loader/index'
const withAuth = Component => {
const Auth = (props) => {
const { isError } = useUser(); //My hook which is calling /api/user see if there is a user
const router = useRouter()
if …Run Code Online (Sandbox Code Playgroud) reactjs ×10
javascript ×3
css ×1
ecmascript-6 ×1
jsx ×1
material-ui ×1
next-router ×1
next.js ×1
react-router ×1
recompose ×1
redux ×1
wrapper ×1