【问题标题】:Cannot read properties of undefined (reading '4')无法读取未定义的属性(读取“4”)
【发布时间】:2022-01-15 08:41:45
【问题描述】:

我知道有很多类似的问题,但我已经尝试了每个问题,但仍然无法解决。

嗯,我正在使用 typescript 和 styled-components 构建自己的 ui 库。老实说,我是 TS 的新手,所以我可能会遗漏一些明显的东西,所以任何建议都将不胜感激。

现在开始重要的事情,这里是一些代码:

  /// THIS IS IN THE PROJECT I'M TRYING TO USE MY LIBRARY
  <Button 
        size={4}
      >
        My cool button
  </Button>

如您所见,我将 size 属性传递给我自己的库的 Button 组件。这个道具在这里被图书馆接收:

const Button = (props: IButtonProps) => {
  return (
    <StyledButton {...props}>
     {props.leftIcon && <ButtonIcon marginRight={props.iconSpacing}>{props.leftIcon}</ButtonIcon>}
     {props.children}
     {props.rightIcon && <ButtonIcon marginLeft={props.iconSpacing}>{props.rightIcon}</ButtonIcon>}
    </StyledButton>
  )
}

现在你可以看到我有 &lt;StyledButton&gt; 使用 styled-components 我正在传播道具:

const StyledButton = styled.button<IButtonProps>`
   // Other properties

  padding: ${props => props.theme.paddings[props.size as SizeTypes ?? 4]};

  // More properties

问题就在这里。当我使用库从项目中传递size={4} 时,标题中出现错误。

当然,我已经用我的对象及其属性定义了 DeafultTheme

import 'styled-components'

declare module 'styled-components' {
  export interface DefaultTheme {

    // Some objects
   
    paddings: {
      1: string,
      2: string,
      3: string,
      4: string,
      5: string,
      6: string,
      7: string,
      8: string
    };

    // More objects
  }
}

还有一个 theme 正在使用它:

import { DefaultTheme } from 'styled-components';

const theme: DefaultTheme = {
  paddings: {
    1: '2px',
    2: '4px',
    3: '6px',
    4: '8px',
    5: '10px',
    6: '12px',
    7: '16px',
    8: '24px',
  }
};

export { theme };

最后,我的IButtonProps界面:

interface IButtonProps extends React.ComponentPropsWithoutRef<'button'> {
  onClick?: (evt: React.FormEvent<HTMLElement>) => void;
  bg?: string;
  size: number;
  spacing: number;
  fontSize?: string;
  fontWeight?: string;
  borderRadius: number;
  color?: string;
  iconSpacing?: number;
  leftIcon?: React.ReactElement;
  rightIcon?: React.ReactElement;
  children?: React.ReactNode;
}

export { IButtonProps };

如果有其他内容可以为您提供更多信息以帮助我,我当然会编辑帖子。

提前致谢!

【问题讨论】:

  • 你能创建一个 jsfiddle 吗?
  • 数字不是有效的属性名称Reference。您有两种选择:1. 用引号将数字括起来(使它们成为字符串)或使用 Map 对象 (comparison),其中数字是有效的键名。
  • 对不起@Jashwant 我尝试使用我正在构建的库但无法使其工作。 RandyCasburn 非常感谢。我正在尝试的路上。我会尽快更新高级的。
  • 好吧,我试过你的答案@RandyCasburn,但我仍然收到同样的错误信息。
  • 好吧,我解决了。 @ghybs 你是绝对正确的,我没有用theme 对象嵌入我的组件,所以我没有在Styled const 中获取该对象。非常感谢。我想我喝的啤酒在我的大脑中形成了如此基本的突触,哈哈。我稍后会编辑我的答案。

标签: javascript reactjs typescript styled-components


【解决方案1】:

正如我在 cmets 中所说,我犯了一个明显的错误:我忘记使用 theme 对象嵌入我的组件。

所以我创建了一个新的ThemeWrapper.tsx 组件,其中包含一个ThemeProvider 提供程序,它将theme 传递给每个children 道具(库的组件):

import * as React from 'react';
import { ThemeProvider } from 'styled-components'
import { theme } from './theme';

const ThemeWrapper: React.FC = ({ children }) => {
  return (
    <ThemeProvider theme={theme}>
      {children}
    </ThemeProvider>
  )
};

export { ThemeWrapper };

在我的Button.tsx 组件中:

const Button = (props: IButtonProps) => {
  return (
    <>
      <ThemeWrapper> --> Pay attention at this.
        <StyledButton {...props}>
          {props.leftIcon && <ButtonIcon mr={props.leftIconSpacing}>{props.leftIcon}</ButtonIcon>}
          {props.children}
          {props.rightIcon && <ButtonIcon ml={props.rightIconSpacing}>{props.rightIcon}</ButtonIcon>}
        </StyledButton>
      </ThemeWrapper>
    </>
  )
}

谢谢!

【讨论】:

    【解决方案2】:

    我刚刚写了一个运行良好的简单示例。也许你能找到你和我的不同之处。

    https://codesandbox.io/s/flamboyant-leaf-y4oyh?file=/src/App.js

    import styled, { ThemeProvider } from "styled-components";
    
    const paddingMap = {
      1: "10px",
      2: "20px",
      3: "30px",
      4: "40px"
    };
    
    const StyledButton = styled.button`
      font-size: ${(props) => props.theme.padding[props.size ?? 4]};
    `;
    
    const Button = (props) => {
      return <StyledButton {...props} />;
    };
    
    export default function App() {
      return (
        <ThemeProvider theme={{ padding: paddingMap }}>
          <div className="App">
            <Button>my default button</Button>
            <Button size={4}>my size 4 button</Button>
            <Button size={3}>my size 3 button</Button>
            <Button size={2}>my size 2 button</Button>
            <Button size={1}>my size 1 button</Button>
          </div>
        </ThemeProvider>
      );
    }
    
    

    【讨论】:

    • 我不确定它如何解决我当前的问题,但我会尝试一下。仍然感谢您的回答。
    • 给您的提示:console.log(props.theme) 在您的样式组件中查看您的填充是否被覆盖。
    猜你喜欢
    • 2019-11-11
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2021-12-31
    • 2021-12-13
    • 2021-11-28
    相关资源
    最近更新 更多