React HOC:将数据属性传递给包装组件的第一个 child/element
React HOC: Pass data attributes to the first child/element of wrapped component
我有一个这样的 hoc 组件:
export const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => (
<WrappedComponent {...props} data-test-id="this-is-a-element" />
);
return ModifiedComponent;
};
export default withAttrs;
我是这样使用它的:
import React from 'react';
import withAttrs from './withAttrs';
const SomeLink = () => <a><p>hey</p</a>;
export default withAttrs(SomeLink);
我希望有这样的锚标签:
<a data-test-id="this-is-a-element"><p>hey</p></a>
但是 hoc
不会将 data-attribute
添加到第一个元素。有办法实现吗?
But the hoc doesn't add the data-attribute to the first element.
不是 HOC 没有添加它,而是 SomeLink
,它对 HOC 传递给它的道具没有任何作用。
简单的答案是更新SomeLink
:
const SomeLink = (props) => <a {...props}><p>hey</p></a>;
到目前为止,这是比以下更好的做法。
如果你做不到,你 可以 让你的 HOC 在事后添加 属性,但让 HOC 到达内部似乎不合适组件和改变的东西。事实上,React 使它创建的元素对象不可变,这强烈建议你不要试图弄乱它们。
仍然有可能,这可能只是个坏主意:
export const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => {
// Note we're *calling* the function, not just putting it in
// a React element via JSX; we're using it as a subroutine of
// this component rather than as its own component.
// This will only work with function components. (You could
// write a version that handles class components as well,
// but offhand I don't think you can make one HOC that handles
// both in this case.)
const result = WrappedComponent(props);
return {
...result,
props: {
...result.props,
"data-test-id": "this-is-a-element",
},
};
};
return ModifiedComponent;
};
/*export*/ const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => {
// Note we're *calling* the function, not just putting it in
// a React element via JSX; we're using it as a subroutine of
// this component rather than as its own component.
// This will only work with function components. (You could
// write a version that handles class components as well,
// but offhand I don't think you can make one HOC that handles
// both in this case.)
const result = WrappedComponent(props);
// THIS IS PROBABLY A VERY BAD IDEA. React makes these objects
// immutable, probably for a reason. We shouldn't be mucking
// with them.
return {
...result,
props: {
...result.props,
"data-test-id": "this-is-a-element",
},
};
};
return ModifiedComponent;
};
const SomeLink = () => <a><p>hey</p></a>;
const SomeLinkWrapped = withAttrs(SomeLink);
const Example = () => {
return <div>
<div>Unwrapped:</div>
<SomeLink />
<div>Wrapped:</div>
<SomeLinkWrapped />
</div>;
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
/* So we can see that it was applied */
[data-test-id=this-is-a-element] {
color: green;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
同样,我不认为我会这样做,除非作为 非常 最后的手段,如果它在 React 的未来版本中出现问题,我不会感到惊讶。
我有一个这样的 hoc 组件:
export const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => (
<WrappedComponent {...props} data-test-id="this-is-a-element" />
);
return ModifiedComponent;
};
export default withAttrs;
我是这样使用它的:
import React from 'react';
import withAttrs from './withAttrs';
const SomeLink = () => <a><p>hey</p</a>;
export default withAttrs(SomeLink);
我希望有这样的锚标签:
<a data-test-id="this-is-a-element"><p>hey</p></a>
但是 hoc
不会将 data-attribute
添加到第一个元素。有办法实现吗?
But the hoc doesn't add the data-attribute to the first element.
不是 HOC 没有添加它,而是 SomeLink
,它对 HOC 传递给它的道具没有任何作用。
简单的答案是更新SomeLink
:
const SomeLink = (props) => <a {...props}><p>hey</p></a>;
到目前为止,这是比以下更好的做法。
如果你做不到,你 可以 让你的 HOC 在事后添加 属性,但让 HOC 到达内部似乎不合适组件和改变的东西。事实上,React 使它创建的元素对象不可变,这强烈建议你不要试图弄乱它们。
仍然有可能,这可能只是个坏主意:
export const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => {
// Note we're *calling* the function, not just putting it in
// a React element via JSX; we're using it as a subroutine of
// this component rather than as its own component.
// This will only work with function components. (You could
// write a version that handles class components as well,
// but offhand I don't think you can make one HOC that handles
// both in this case.)
const result = WrappedComponent(props);
return {
...result,
props: {
...result.props,
"data-test-id": "this-is-a-element",
},
};
};
return ModifiedComponent;
};
/*export*/ const withAttrs = (WrappedComponent) => {
const ModifiedComponent = (props) => {
// Note we're *calling* the function, not just putting it in
// a React element via JSX; we're using it as a subroutine of
// this component rather than as its own component.
// This will only work with function components. (You could
// write a version that handles class components as well,
// but offhand I don't think you can make one HOC that handles
// both in this case.)
const result = WrappedComponent(props);
// THIS IS PROBABLY A VERY BAD IDEA. React makes these objects
// immutable, probably for a reason. We shouldn't be mucking
// with them.
return {
...result,
props: {
...result.props,
"data-test-id": "this-is-a-element",
},
};
};
return ModifiedComponent;
};
const SomeLink = () => <a><p>hey</p></a>;
const SomeLinkWrapped = withAttrs(SomeLink);
const Example = () => {
return <div>
<div>Unwrapped:</div>
<SomeLink />
<div>Wrapped:</div>
<SomeLinkWrapped />
</div>;
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
/* So we can see that it was applied */
[data-test-id=this-is-a-element] {
color: green;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
同样,我不认为我会这样做,除非作为 非常 最后的手段,如果它在 React 的未来版本中出现问题,我不会感到惊讶。