We will build a simple app for inviting people to our event.
1. To start a new Create React App project with TypeScript, you can run:
npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript
2. Define type definition for our state
In our App.tsx file we can define the type definition
import React, { useState } from "react";
import List from "./components/List";
import "./App.css";
import AddToList from "./components/AddToList";
// Type definition
export interface IState {
people: {
name: string;
age: number;
url: string;
{/* The question mark is used to mark that variable as an
optional variable */}
note?: string;
}[];
}
function App() {
// we can pass our interface to our useState
const [people, setPeople] = useState<IState["people"]>([
{
name: "Jean Luc Tuyishime",
url: "https://cdn.nba.com/headshots/nba/latest/1040x760/2544.png",
age: 44,
note: "Lorem ipsum dollar sit amet",
},
]);
return (
<div className="App">
<p>people invited to my party</p>
<List people={people} />
<AddToList people={people} setPeople={setPeople} />
</div>
);
}
export default App;
We have also imported two files List.tsx and AddToList.tsx and passed people and setPeople as props.
3. In our List.tsx file
we can import and pass props with typescript
import React from "react";
import { IState as IProps } from "../App";
// Pass props with typescript
const List: React.FC<IProps> = ({ people }) => {
{/* Here we are returning a JSX element */}
const renderList = (): JSX.Element[] => {
return people.map((person) => {
return (
<li className="List">
<div className="List-header">
<img className="List-img" src={person.url} />
<h2>{person.name}</h2>
</div>
<p>{person.age} years old</p>
<p className="List-note">{person.note}</p>
</li>
);
});
};
return <div>{renderList()}</div>;
};
export default List;
4. In our AddToList.tsx file
import React, { useState } from "react";
import { IState as Props } from "../App";
// Type definition for our state (people) passed as props.
interface IProps {
people: Props["people"];
setPeople: React.Dispatch<React.SetStateAction<Props["people"]>>;
}
const AddToList: React.FC<IProps> = ({ people, setPeople }) => {
const [input, setInput] = useState({
name: "",
age: "",
note: "",
img: "",
});
// type definition for our event => (e).
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
): void => {
setInput({
...input,
[e.target.name]: e.target.value,
});
};
// void is used here because we are not returning any value
const handleClick = (): void => {
if (!input.name || !input.age || !input.img) return;
setPeople([
...people,
{
name: input.name,
age: parseInt(input.age),
note: input.note,
url: input.img,
},
]);
setInput({
name: "",
age: "",
note: "",
img: "",
});
};
return (
<div className="AddToList">
Add To List Component
<input
type="text"
placeholder="Name"
value={input.name}
className="AddToList-input"
onChange={handleChange}
name="name"
/>
<input
type="text"
placeholder="Age"
value={input.age}
className="AddToList-input"
onChange={handleChange}
name="age"
/>
<input
type="text"
placeholder="Image Url"
value={input.img}
className="AddToList-input"
onChange={handleChange}
name="img"
/>
<textarea
placeholder="Notes"
value={input.note}
className="AddToList-input"
onChange={handleChange}
name="note"
/>
<button onClick={handleClick} className="AddToList-btn">
Add To List
</button>
</div>
);
};
export default AddToList;
Top comments (0)