【问题标题】:How to pass styles via props with styled components without having to create the component inside the component如何通过带有样式组件的道具传递样式,而无需在组件内创建组件
【发布时间】:2021-06-17 00:57:22
【问题描述】:

如果不在Text 组件内创建styled-component,我找不到另一种方法来赋予我的道具动态样式。为了性能,我想在 Text 组件之外创建组件。

样式化组件

import React, { ReactChildren } from 'react'
import styled from 'styled-components'


export const Text = ({ as = 'p', children, styles = {} }) => {
  const newStyles = Object.entries(styles).reduce((acc, [key, value]) => {
    return `${acc}${key}: ${value};`
  }, '')
  const Component = styled.p`
    ${newStyles}
    color: #000;
  `
  return <Component as={as}>{children}</Component>
}

所需用途

<Text styles={{ height: "10px" }} />

输出 HTML

<p styles="height: 10px" />

【问题讨论】:

  • 你不能在 styled-component 之外做 Object.entries 位并将其传入吗?
  • 是的,但问题在于 Component 包含在 Text 组件中。因此,如果我将两者都取出,我将无法从函数中返回组件。但也许我可以,但我只是看不到它:p

标签: javascript reactjs styled-components


【解决方案1】:

上面的代码令人困惑,因为您想将样式应用于 DOM style 属性,但您还将它们作为 CSS 样式应用于类名。无需创建此组合组件,因为 styled-components 无需组合即可处理 aschildrenstyle 属性:

示例 1:

import React from "react";
import styled, { Interpolation } from "styled-components";

export type TextProps = {
  as?: string | React.ComponentType<any>;
  children: React.ReactNode;
  styles?: Interpolation<React.CSSProperties>;
};

const Component = styled.p<TextProps>`
  ${({ styles }) => styles}
  color: #000;
`;

export const Text = ({
  as,
  children,
  styles
}: TextProps): React.ReactElement => (
  <Component styles={styles} as={as}>
    {children}
  </Component>
);

export default Text;

示例 2:

import styled from "styled-components";

const Text = styled.p`
  color: #000;
`;

export default Text;

示例 3:

import * as React from "react";
import styled from "styled-components";

export type TextComponentProps = {
  className?: string;
  children: React.ReactNode;
  styles?: React.CSSProperties;
};

const TextComponent = ({
  children,
  className,
  styles
}: TextComponentProps): React.ReactElement => (
  <p className={className} style={styles}>
    {children}
  </p>
);

const Text = styled(TextComponent)`
  color: #000;
`;

export default Text;

用法:

import * as React from "react";
import Box from "./Box";
import Text from "./Text";
import Text2 from "./Text2";
import Text3 from "./Text3";
import "./styles.css";

const App = (): React.ReactElement => (
  <div className="app">
    <h1>Example 1 - "styles" as CSS Styles</h1>
    <Box>
      <Text styles={{ height: "10px" }}>Hello</Text>
      <Text as="h1">Goodbye</Text>
    </Box>
    <hr />
    <h1>Example 2 - "style" as DOM styles</h1>
    <Box>
      <Text2 style={{ height: "10px" }}>Hello</Text2>
      <Text2 as="h1">Goodbye</Text2>
    </Box>
    <hr />
    <h1>Example 3 - "styles" as DOM styles</h1>
    <Box>
      <Text3 styles={{ height: "10px" }}>Hello</Text3>
      <Text3 as="h1">Goodbye</Text3>
    </Box>
  </div>
);

export default App;

输出:

在这方面,听起来你可能正在尝试做我对composabled-styled-components 所做的事情,尽管我不推荐它,因为它是doesn't work with SSR apps

【讨论】:

  • 谢谢马特...有趣的是,这不是有效的 TS,当然我在原始问题中没有提到。
  • 更新了答案以包括打字稿示例 + 打字稿代码框。
  • 在相关说明中,如果您想在 styles 属性中插入 props 以将 CSS 样式添加到类名,则使用 css 辅助函数(您可以插入对象或模板文字)。
  • 这非常有帮助。谢谢!
  • 谢谢!!我将此解决方案与故事书一起使用并且效果很好......我如何使用它,但在 react-native 中?我正在使用故事书,但不能让它工作,你知道吗?
【解决方案2】:

您可以在样式化组件上创建ref,以便在效果中设置样式,如下所示:

const Component = styled.p`
  background-color: red;
`;

const Text = ({ as = 'p', children, styles = {} }) => {
  const newStyles = Object.entries(styles).reduce((acc, [key, value]) => {
    return `${acc}${key}: ${value};`
  }, '')
  
  const ref = React.createRef();

  React.useEffect(() => {
    ref.current.style = newStyles;
  }, []);
  
  return <Component ref={ref} as={as}>{children}</Component>
}

ReactDOM.render(<Text styles={{ height: "10px" }}>This paragraph is 10px high</Text>, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script></script>
<script src="https://unpkg.com/react-is@17/umd/react-is.production.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>

<div id="root"></div>

【讨论】:

  • 非常有趣的解决方案。我觉得很奇怪,我需要使用渲染的 DOM 而不是为此使用 react。我会考虑的,谢谢
猜你喜欢
  • 2021-04-29
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 2019-09-23
  • 2020-04-28
相关资源
最近更新 更多