我有两个将上下文添加到组件的HOC,如下所示:
const withContextOne = Component => class extends React.Component {
render() {
return (
<ContextOne.Consumer>
{context => <Component {...this.props} one={context} /> }
</ContextOne.Consumer>
);
}
};
export default withContextOne;
我只想要一种语法简洁的方法,用此HOC包装组件,以免对我的JSX结构造成太大影响。
export default withContextOne(withContextTwo(MyComponent))
这种方式最简洁,但是很遗憾,这破坏了我的单元测试。尝试从JSX内部评估HOC,例如:
{ withContextOne(withContextTwo(<Component />)) }
这给我说了一个错误
函数作为React子代无效。如果您从渲染中返回一个Component而不是
,则可能会发生这种情况。
在渲染之前创建一个变量来存储HOC组件:
const HOC = withContextOne(Component)
然后仅使用<HOC {...props}/>
等进行渲染。我不喜欢这种方法,因为它会更改JSX中组件的名称
答案 0 :(得分:1)
您可以在返回包装的组件之前设置<html>
<head>
<title></title>
<style type="text/css" media="screen">
</style>
<script type="text/javascript" src="jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(function () {
$.get('inputfile.txt', function(data) {
//If the returned data is not empty or whitespace
if (data) {
// split the string into several strings when a new line occures
var lines = data.split('\n'); // Take note of the \n This is the new line character also known as a line ending, end of line (EOL), or line break.
// If there are more than 0 lines
if (lines.length > 0) {
// For every line console.log out what the line is with the line number prepended.
var $content = $('#content'); //grab the content area
for (var i = 0; i < lines.length; i++) {
console.log(i + ": " + lines[i]);
$content.html($content.html() + "\n" + i + ": " + lines[i]); //insert a new line into the content area
}
}
} else {
// It is empty, do somethin else
alert('no data present in txt file.');
}
});
});
</script>
</head>
<body>
<pre id="content"></pre><!-- Added a place for the content -->
</body>
</html>
。
displayName
这会将const withContextOne = Component => {
class WithContextOneHOC extends React.Component {
render() {
return (
<ContextOne.Consumer>
{context => <Component {...this.props} one={context} /> }
</ContextOne.Consumer>
);
}
}
WithContextOneHOC.displayName = `WithContextOneHOC(${Component.displayName})`;
return WithContextOneHOC;
};
放入您的React树中,而不仅仅是一般的React <WithContextOneHOC(YourComponentHere)>
元素。
答案 1 :(得分:1)
您可以使用装饰器减轻链接式HOC的语法痛苦。我忘记了您需要使用哪个特定的babel插件,取决于您的babel版本,它可能仍然是babel-plugin-transform-decorators-legacy
或可能是babel-plugin-transform-decorators
。
例如:
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import { injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { resizeOnScroll } from './Resize';
@withRouter
@resizeOnScroll
@injectIntl
@connect(s => s, (dispatch) => ({ dispatch }))
export default class FooBar extends Component {
handleOnClick = () => {
this.props.dispatch({ type: 'LOGIN' }).then(() => {
this.props.history.push('/login');
});
}
render() {
return <button onClick={}>
{this.props.formatMessage({ id: 'some-translation' })}
</button>
}
}
但是,对于装饰器的警告是测试变得很痛苦。您不能将装饰器与const
一起使用,因此,如果要导出“干净的”未修饰的类,则很不走运。这是我现在通常要做的,纯粹是为了进行测试:
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import { injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { resizeOnScroll } from './Resize';
export class FooBarUndecorated extends Component {
handleOnClick = () => {
this.props.dispatch({ type: 'LOGIN' }).then(() => {
this.props.history.push('/login');
});
}
render() {
return <button onClick={}>
{this.props.formatMessage({ id: 'some-translation' })}
</button>
}
}
export default withRouter(
resizeOnScroll(
injectIntl(
connect(s => s, ({ dispatch }) => ({ dispatch }))(
FooBarUndecorated
)
)
)
);
// somewhere in my app
import FooBar from './FooBar';
// in a test so I don't have to use .dive().dive().dive().dive()
import { FooBarUndecorated } from 'src/components/FooBar';