Не удается прочитать свойства undefined (чтение ‘4’)

#javascript #reactjs #typescript #styled-components

#javascript #reactjs #typescript #styled-компоненты

Вопрос:

Я знаю, что есть много вопросов, похожих на этот, но я уже пробовал каждый из них, и я все еще не могу заставить его работать.

Ну, я создаю свою собственную библиотеку пользовательского интерфейса, используя typescript и styled-компоненты. Честно говоря, я довольно новичок в TS, поэтому есть вероятность, что я пропустил что-то очевидное, поэтому любой совет будет оценен.

Теперь перейдем к тому, что имеет значение, вот это некоторый код:

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

Как вы можете видеть, я передаю size prop компоненту Button своей собственной библиотеки. Этот реквизит получен библиотекой здесь:

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

И теперь, как вы можете видеть, у меня есть <StyledButton> using styled-components, где я распространяю реквизит:

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

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

  // More properties
 

И проблема именно здесь. Когда я перехожу size={4} из проекта, используя библиотеку, я получил ошибку в названии.

Конечно, я уже определил a 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 };
 

Если есть что-то еще, что могло бы дать вам больше информации, чтобы помочь мне, я, конечно, отредактирую сообщение.

Заранее спасибо!

Комментарии:

1. Можете ли вы создать jsfiddle?

2. Число не является допустимой ссылкой на имя свойства. У вас есть два варианта: 1. Заключите числа в кавычки (превратив их в строки) или используйте объект Map ( сравнение ), в котором указаны допустимые имена ключей.

3. Извините @Jashwant Я пытался использовать библиотеку, которую я создаю на ней, но не смог заставить ее работать. RandyCasburn Большое вам спасибо. Я собираюсь попробовать это. Я обновлю с помощью advanced КАК можно скорее.

4. Ну, я попробовал ваш ответ @RandyCasburn, но я все равно получил то же сообщение об ошибке.

5. Ну, я решил это. Вы были абсолютно правы @ghybs, я не вставлял свой компонент в theme объект, поэтому я не получал этот объект в Styled const. Большое спасибо. Я думаю, что пиво, которое я выпил, создало такой базовый синапс в моем мозгу, лол. Я отредактирую свой ответ позже.

Ответ №1:

Я только что написал простой пример, который хорошо работает. Может быть, вы сможете найти различия между вашим и моим.

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>
  );
}

 

Комментарии:

1. Я не уверен, как это решает мою текущую проблему, но я попробую. Все еще благодарен за ваш ответ.

2. Подсказка для вас: console.log(props.theme) в вашем стилизованном компоненте проверьте, были ли перезаписаны ваши отступы.

Ответ №2:

Как я уже сказал в комментариях, я допустил очевидную ошибку: Я забыл присвоить мои компоненты theme object.

Итак, я создал новый ThemeWrapper.tsx компонент с ThemeProvider поставщиком, который передает theme каждому children prop (компонентам библиотеки):

 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 amp;amp; <ButtonIcon mr={props.leftIconSpacing}>{props.leftIcon}</ButtonIcon>}
          {props.children}
          {props.rightIcon amp;amp; <ButtonIcon ml={props.rightIconSpacing}>{props.rightIcon}</ButtonIcon>}
        </StyledButton>
      </ThemeWrapper>
    </>
  )
}
 

Спасибо!