I am using React- typescript for my app. For Styling I am using Styled-components. I have created one global button component. Inside the button component i used loader. My target is when user will click the button it will display loading. From the parent component I have created one fake api call and in there I added settime-out
5s. But when I click the button it does not display the loader which was in Button component. From the parent component set-time out works and it display in my console. I don't know why it does not the display the loading ....
. Also i added the disabled option when fake api will call button should be disabled. That logic also does not work.
Here is the Button component
import * as React from "react";
import styled, { css } from "styled-components";
interface IButtonProps {
children?: React.ReactChild;
className?: string;
size?: "small" | "medium" | "big";
themes?: "primary" | "secondary" | "dark" | "light";
disabled?: boolean;
loading?: boolean;
style?: React.CSSProperties;
onClick?: () => void;
onSubmit?: () => void;
}
const Button = ({
children,
className,
size,
themes,
disabled,
loading,
style,
onClick,
onSubmit
}: IButtonProps) => (
<button
className={className}
onClick={onClick}
onSubmit={onSubmit}
style={
disabled && disabled
? { opacity: 0.5, pointerEvents: `none` }
: loading ? { ...style, pointerEvents: `none` } : //This is my disabled condition.
style
}
>
{loading ? <p>loading...</p> : children} //This is my loading condition.
</button>
);
const sizes = {
small: css`
padding: 5px 20px;
font-size: 12px;
`,
medium: css`
padding: 10px 30px;
font-size: 14px;
`,
big: css`
padding: 15px 40px;
font-size: 18px;
`
};
const ButtonThemes = {
primary: css`
border: 1px solid tomato;
background: tomato;
color: white;
`,
secondary: css`
border: 1px solid palevioletred;
background: palevioletred;
color: white;
`,
dark: css`
border: 1px solid #273444;
background: #273444;
color: white;
`,
light: css`
border: 1px solid #eff2f7;
background: #f9fafc;
color: #273444;
`
};
const StyledButton = styled(Button)`
${({ size = "small" }) => sizes[size]};
${({ themes = "primary" }) => ButtonThemes[themes]};
outline: none;
border-radius: 5px;
cursor: pointer;
`;
export default StyledButton;
This is my parent component. Where I used settimeout and import Button component.
const handleClick = () => {
setTimeout(() => {
console.log("check it out") //It does display when the button click
}, 5000);
}
//This is the Button
<Button size="medium" themes="primary" onClick={handleClick}>click</Button>
You should create a loading
state by using useState
hook if your parent component is function component
, if using class component
you can define a state in constructor like this this.state = { loading: false }
in your parent component, and set it to true
in handleClick
and pass the state as prop to your Button
component:
// In case function component
const [loading, setLoading] = useState(false);
const handleClick = () => {
setLoading(true);
setTimeout(() => {
setLoading(false); // When finish, set it to false
console.log("check it out") //It does display when the button click
}, 5000);
}
//This is the Button
<Button
size="medium"
themes="primary"
onClick={handleClick}
loading={loading}
>
click
</Button>