Reputation: 7324
I have a react component in typescript and I want to set the results of an appsync graphql query to a property in state.
import React, { Component } from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import {ListProjectsQuery} from './API'
import {listProjects } from './graphql/queries';
class App extends Component<{}, {
projects:ListProjectsQuery
}> {
state = {
projects: null
};
async componentDidMount() {
const projects = await API.graphql(graphqlOperation(listProjects));
this.setState({ projects });
}
...
How do I define the default state property to make this work?
I found a similar problem in the amplify github issues but that solution was in the context of a stateless functional component. I am using a stateful component.
Depending on what I try I seem to get one of three errors.
The code above throws Type 'null' is not assignable to type 'ListProjectsQuery'.
.
This makes sense so I try and map the shape in state like so:
state = {
projects: {listProjects: {items: [{name: ''}]}}
}
which makes it throw Types of property 'projects' are incompatible.
I either get told that a Property does not exist on type 'Observable<object>'
or I get told the shape of the default state value is not compatible.
Finally I tried to use an interface like in the example I found:
interface IListProjectQuery {
projects: ListProjectsQuery;
}
and then I reference the interface
class App extends Component<
{},
{
projects: IListProjectQuery;
}
>
and it throws the following error Type '{ projects: null; }' is not assignable to type 'Readonly<{ projects: IListProjectQuery; }>'.
What value do I give the default state property in order for it to make typescript happy?
The ListProjectsQuery
import is autogenerated by amplify/appsync codegen, the type alias looks like so:
export type ListProjectsQuery = {
listProjects: {
__typename: "ModelProjectConnection",
items: Array< {
__typename: "Project",
id: string,
name: string,
organisation: {
__typename: "Organisation",
id: string,
name: string,
} | null,
list: {
__typename: "ModelListConnection",
nextToken: string | null,
} | null,
} | null > | null,
nextToken: string | null,
} | null,
};
Upvotes: 5
Views: 4236
Reputation: 2659
export type IProject = {
name: string
}
export type GetProjectsQuery = {
listProjects:{
items: IProject[]
nextToken: string
}
}
const fetchAllProjects = async () => {
try {
const result = (await API.graphql(graphqlOperation(queries.listProjects))) as {
data: GetProjectsQuery
}
projects = result.data.listProjects.items
} catch (error) {
//handle error here
}
Upvotes: 7
Reputation: 8265
Make your property optional:
class App extends Component<{}, {
projects?: ListProjectsQuery //<<== note the question mark
}> {
state = {
projects: null
};
async componentDidMount() {
const projects = await API.graphql(graphqlOperation(listProjects));
this.setState({ projects });
}
Upvotes: 1