Typescript React Tutorial - Typescript React Props, Usestate Typescript and React Context Typescript
In this post you will learn how to use Typescript together with React.
Project generation
Our first step would be to generate a React project with Typescript. You could use for it create-react-app
but I highly recommend you to look on Vite tool. It allows you to generate project with different frameworks and it is extremely fast.
To generate a project I'm using
npm create vite@latest react-ts
Where react-ts
is a name of the project
Here we need to select React as a framework and choose that we want Typescript with it.
Now we can remove everything from App component and start working.
const App = () => {
return <h1>Monsterlessons Academy</h1>
}
JSX.Element
Most often in React we create components and provide props inside. Let's say that we want to create a custom Button component.
const Button = ({
text = "submit",
icon,
}) => {
return (
<button>
{icon && <span>{icon}</span>}
{text}
</button>
);
};
const App = () => {
return (
<div>
<h1>Monsterlessons Academy</h1>
<Button text="Fooo" icon="▼"></Button>
</div>
)
}
Out Button
has text
and icon
as props.
Now let's add a bit of Typescript. First of all let's defined what our Button
must return
```javascript
const Button = ({
...
}): JSX.Element => {
We specified here JSX.Element
which is React markup. If we return a string or undefined we will directly see a warning from Typescript.
Interface for props
Secondly let's define the interface for all possible props in our Button
component. In this case it will be more safe.
interface ButtonProps {
text?: string;
icon?: string;
}
const Button = ({
text = "submit",
icon,
}: ButtonProps): JSX.Element => {
We created an interface where both properties are strings and they are optional. Not we used ButtonProps
inside our props and we are sure that we won't pass any wrong props inside.
Children
Really often we have children that we want to provide to our components. How we can define them with Typescript?
interface ButtonProps {
text?: string;
icon?: string;
children?: JSX.Element;
}
const Button = ({
text = "submit",
icon,
children,
}: ButtonProps): JSX.Element => {
return (
<button>
{icon && <span>{icon}</span>}
{text}
{children && children}
</button>
);
};
Here we added an optional children
property which is essentially a JSX.Element
. We also rendered children
from the props inside the component if they are provided. In this case we are safe that only correct React markup can be provided as a content inside the component.
Working with React hooks
But what about React hooks? Most often you would want to provide correct data type in your useState
hook.
interface User {
id: string;
name: string;
}
const App = () => {
const [user, setUser] = useState<User | null>(null);
}
It makes sure that we can set and get from the user only properties which are specified. In this case it is either a User
interface or null
.
Working with React classes
You must also know how to work with React classes inside Typescript. Yes I know that classes is an older approach but it is still not deprecated and you might get a project with classes inside React.
interface AppState {
currentUser?: User;
}
class App extends Component<{}, AppState> {
componentDidMount() {
this.setState({ currentUser: { id: "1", name: "foo" } });
}
render(): JSX.Element {
return (
<div>
<h1>Monsterlessonss Academy</h1>
<Button text="Fooo" icon="▼"></Button>
</div>
);
}
}
Here we converted our App
in the class. When we extend from React class we provide inside props interface as a first argument and state interface as a second argument. In our case props are empty but we created AppState
interface with currentUser
which we can set.
Working with React context
The last thing that I want to show you is how to work with React context.
const AppContext = createContext({ theme: "light" });
const App = () => {
const appContext = useContext(AppContext);
return (
<AppContext.Provider value={{ theme: "dark" }}>
<h1>Monsterlessonss Academy</h1>
<Button text="Fooo" icon="▼"></Button>
</AppContext.Provider>
);
};
We didn't write any additional interfaces but just used createContext
and useContext
. Nevertheless Typescript fully understands what properties are available inside our context and gives us a correct autocomplete and validation in appContext
when we use it.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!
📚 Source code of what we've done