How to wrap up Ant Design with Styled Components and TypeScript?

前端 未结 5 1531
独厮守ぢ
独厮守ぢ 2021-02-13 15:47

I want to wrap up my ant-design components with styled-components, I know that this is possible (https://gist.github.com/samuelcastro/0ff7db4fd54ce2b80cd1c34a85b40c08) however I

相关标签:
5条回答
  • 2021-02-13 16:18

    I have found this ancient question and try to solve in an easy way:

    import React from 'react';
    import styled from 'styled-components';
    import { Card } from 'antd';
    import { CardProps } from 'antd/lib/card';
    
    export const NewCard: React.FunctionComponent<CardProps> = styled(Card)`
      margin-bottom: 24px;
    `;
    

    without render props :D

    if you just need wrap a component as function component, that's all right. But you will lose the properties of class component such as Card.Meta.

    There is a workaround:

    import React from 'react';
    import styled from 'styled-components';
    import { Card } from 'antd';
    import { CardProps } from 'antd/lib/card';
    
    export const NewCard: typeof Card = styled(Card)<CardProps>`
      margin-bottom: 24px;
    ` as any;
    

    Everything (maybe... XD) works as original Antd Component ;)

    0 讨论(0)
  • 2021-02-13 16:18

    my code is here. and it is work.

    
    import React from 'react';
    import { Button as AntButton } from 'antd';
    import { ButtonProps } from 'antd/lib/button/button';
    import styled from 'styled-components';
    
    const Container = styled.div`
      font-size: 20px;
    `;
    
    
    const Button: React.FunctionComponent<ButtonProps> = styled(AntButton)`
      margin-top: 24px;
      margin-left: 30px;
    `;
    
    export default function Home() {
      return (
        <Container>
          Hello World
          <Button type="primary">test</Button>
        </Container>
      );
    }
    
    
    
    
    0 讨论(0)
  • 2021-02-13 16:27

    The above solutions didn't work for me, this solved it though.

    const Button = styled((props: NativeButtonProps) => <AntButton {...props} />)``;
    
    0 讨论(0)
  • 2021-02-13 16:28

    index.tsx (Button Component)

    import { Button as AntButton } from 'antd'
    import { NativeButtonProps } from 'antd/lib/button/button'
    import 'antd/lib/button/style/css'
    import * as React from 'react'
    import styledComponents from 'styled-components'
    import * as colours from '../colours'
    
    const getColour = (props: any) =>
      props.status === 'green'
        ? colours.STATUS_GREEN
        : props.status === 'red'
          ? colours.STATUS_RED
          : props.type === 'primary'
            ? colours.PRIMARY
            : colours.WHITE
    
    export interface ButtonProps extends NativeButtonProps {
      status?: string
    }
    
    export default styledComponents((props: ButtonProps) => <AntButton {...props} />)`
      &:focus,
      &:hover
      & {
        background-color: ${getColour};
        border-color: ${getColour};
      }
    `
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.2/umd/react-dom.production.min.js"></script>

    import React from 'react'
    import Button, { ButtonProps } from './index'
    
    interface ButtonAsyncSingleSuccessProps extends ButtonProps {
      clickFunc: any, // (...args: any[]) => Promise<any>
      labelLoading: string,
      labelReady: string,
      labelSuccess: string,
    }
    
    interface ButtonAsyncSingleSuccessState {
      label: string,
      loading: boolean,
      status: string
    }
    
    export default class ButtonAsyncSingleSuccess extends React.Component<
      ButtonAsyncSingleSuccessProps,
      ButtonAsyncSingleSuccessState
    > {
      constructor (props: any) {
        super(props)
        this.state = {
          label: props.labelReady,
          loading: false,
          status: ''
        }
      }
      public clickHandler (event: any) {
        const { labelLoading, labelReady, labelSuccess, clickFunc } = this.props
        this.setState({
          label: labelLoading,
          loading: true,
          status: ''
        })
        clickFunc(event)
          .then(() => {
            this.setState({
              label: labelSuccess,
              loading: false,
              status: 'green'
            })
          })
          .catch(() => {
            this.setState({
              label: labelReady,
              loading: false,
              status: 'red'
            })
          })
      }
      public render () {
        const {
          labelLoading,
          labelReady,
          labelSuccess,
          clickFunc,
          ...props
        } = this.props
        const { label, loading, status } = this.state
        if (status === 'red') {
          setTimeout(() => this.setState({ status: '' }), 1000) // flash red
        }
        return (
          <Button
            {...props}
            loading={loading}
            status={status}
            onClick={(e) => this.clickHandler(e)}
          >
            {label}
          </Button>
        )
      }
    }

    0 讨论(0)
  • 2021-02-13 16:33

    The root of the problem seems to be that styled-components expects the inner component (AntButton) to accept all the props in the specified interface (IButtonProps), but AntButton does not accept customProp. To fix this, follow the last example in this section of the documentation and use a stateless function component to remove customProp before calling AntButton.

    export const Button = styledComponents<IButtonProps>(
      ({ customProp, ...rest }) => <AntButton {...rest} />)`
      // any custom style here
    `;
    
    0 讨论(0)
提交回复
热议问题