Learning React - Exercise control over your component state with Typescript
Jon Hilton
Posted on August 23, 2018
The last post left us with a bit of a problem.
Although our user component retrieves and displays data from ASP.NET API, it also flashes up some hard-coded data before the real data shows up.
It seems like we could just remove the hard-coded data so let's try that...
public state = {
"users": []
};
Seems reasonable, except for one problem, it doesn't compile.
Yes that's right, javascript gets compiled these days! And in this case we run into an error.
This seems odd at first, it was working before.
Turns out, when we had our hard-coded data, Typescript was able to infer the type from the structure of this data.
public state = {
"users": [
{ "id": 1, "name": "Jon Hilton", "summary": "36 / Lead Developer" },
{ "id": 2, "name": "Janine Smith", "summary": "32 / Senior Engineer" }
]
};
So, because that data included an id property, everything "just worked".
Now we don't have any data, there's nothing for the compiler to go off, so it blows up when it comes to this line...
{this.state.users.map(user => <UserRow key={user.id} user={user} />)}
Turns out, this isn't a problem if we stop being lazy and actually define types for our state.
export interface IState {
users: IUser[];
}
export interface IUser {
id: number,
name: string,
summary: string
}
Then we can declare our component state's type...
export default class MyUsers extends React.Component<any, IState>{
And finally, tweak the code where we set the initial state (to indicate the type).
public state: IState = {
"users": []
};
Now everything compiles, plus we have the benefit that we've removed the ambiguity about our state.
You'll get proper intellisense in Visual Studio Code and there's less uncertainty all round!
Just before we continue, if you fancy a gander at the source code for this series grab it here :-)
Loading...
This has removed our flash of data, but what if we want to show a loading indicator when the data's being retrieved?
We need a way to render different content if we're loading data, then show the list once the data's available.
As with all things in React, if we can change the underlying state as we're making the API call, the user interface can react to that and show a loading indicator of some kind.
We can add a loading
boolean to IState.
export interface IState {
loading: boolean;
users: IUser[];
}
Set it to false for starters.
public state: IState = {
loading: false,
"users": []
};
Then flip this flag when we're loading data from the back-end.
public async componentDidMount() {
this.setState({ loading: true }); // toggle on
const result = await fetch('https://localhost:44348/api/user');
const users = await result.json();
this.setState({ users, loading: false }); // toggle off
}
And finally make our html react to this and render some kind of loading indicator (when state.loading
is true).
<h1>My Users</h1>
{this.state.loading && <div>Loading...</div>} // add this
<table className="user-list">
<tbody>
{this.state.users.map(user => <UserRow key={user.id} user={user} />)}
</tbody>
</table>
This looks a bit weird the first time you see it so let's break it down.
{this.state.loading && <div>Loading...</div>}
This will show the Loading div if this.state.loading
evaluates to true.
As a C# developer you'll be used to the more classic if
statement.
So what is this &&
madness?!
Turns out, in javascript, the &&
logical operator returns the value of one of the specified operands.
If you have an expression like this.
const isSunday = true;
const result = isSunday && 'It\'s Sunday';
The result would be 'It's Sunday'.
const isSunday = false;
const result = isSunday && 'It\'s Sunday';
And this would return false!
The table over here explains this much better than I'd hope to!
So in the end, this is just a concise way of saying "show the loading indicator if this.state.loading
is true".
Your state is typed!
Whilst it's tempting to throw any
around all over the place to avoid declaring types, this shortcut ultimately makes some things more difficult and removes the benefits of using Typescript in the first place.
Create your types, use conditional rendering and your components will react in a predictable way, based purely on the underlying state of the component.
Remember, if you fancy a gander at the source code for this series, you can grab it here :-)
photo credit: Pranav Bhatt Sign, Southern Africa via photopin (license)
Posted on August 23, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
August 11, 2018