如何在styled-components中动态切换图标?解决ThemeProps类型报错问题
Hey there! Let's figure out how to fix that styled-components error you're seeing, plus get dynamic icon switching working smoothly.
Why you're hitting this error
TypeScript enforces strict type checking, and by default, styled-components' props are typed as ThemeProps<DefaultTheme>—which only includes the theme property. Your custom icon prop isn't recognized in this default type, hence the error. Also, there's a small mix-up in your code: you named the props parameter Icon (that's confusing, since it's not an icon component—it's the entire props object passed to your input).
Step-by-step solution
1. Define a type for your component's props
First, create an interface to tell TypeScript about your custom icon prop (make it optional so the input works with or without an icon):
interface GenericInputProps { icon?: string; }
2. Update your styled component with the correct type
Pass this interface to styled.input so TypeScript recognizes the icon prop, and fix the props parameter name for clarity:
import styled, { css } from 'styled-components'; interface GenericInputProps { icon?: string; } export const GenericInput = styled.input<GenericInputProps>` background-color: #f4f4f4; width: 220px; height: 47px; border: none; border-radius: 50px; font-weight: 600; font-size: 16px; cursor: pointer; letter-spacing: 1px; padding: 15px 30px; -moz-outline-radius: 50px; outline: none; ${({ icon }) => icon && css` background-image: url(${icon}); background-size: 20px; background-position: 10px 50%; background-repeat: no-repeat; color: #c7c7c7; /* Add left padding so text doesn't overlap the icon */ padding-left: 50px; `} ::placeholder { color: #c7c7c7; } `;
Pro tip: I added
padding-left: 50pxwhen the icon is present—this keeps your input text from overlapping the icon, which is a quick UI polish.
3. Switch icons dynamically
Now you can pass different icon URLs to the component to toggle them on the fly. Here's an example in a React component:
import { useState } from 'react'; import { GenericInput } from './path-to-your-component'; function App() { // Start with a default icon const [currentIcon, setCurrentIcon] = useState('/icons/user-profile.svg'); // Toggle between two icons when a button is clicked const switchIcon = () => { setCurrentIcon(prev => prev === '/icons/user-profile.svg' ? '/icons/search-magnifier.svg' : '/icons/user-profile.svg' ); }; return ( <div> <GenericInput icon={currentIcon} placeholder="Enter text here..." /> <button onClick={switchIcon}>Swap Icon</button> </div> ); }
Quick temporary fix (not recommended for production)
If you just want to bypass the type check quickly (great for testing), you can use any for the props type:
export const GenericInput = styled.input<any>` // ... rest of your existing code ${({ icon }) => icon && css` // ... icon styles `} `;
But using proper TypeScript types is way better for long-term maintainability.
内容的提问来源于stack exchange,提问作者Karolina W

