todo/js/components/TodoList.js (81 lines of code) (raw):

// @flow import type {TodoList_user$key} from 'relay/TodoList_user.graphql'; import {useAddTodoMutation} from '../mutations/AddTodoMutation'; import {useMarkAllTodosMutation} from '../mutations/MarkAllTodosMutation'; import Todo from './Todo'; import TodoListFooter from './TodoListFooter'; import TodoTextInput from './TodoTextInput'; import * as React from 'react'; import {graphql, useFragment} from 'react-relay'; type Props = {| userRef: TodoList_user$key, |}; export default function TodoList({userRef}: Props): React.Node { const user = useFragment( graphql` fragment TodoList_user on User { todos( first: 2147483647 # max GraphQLInt ) @connection(key: "TodoList_todos") { __id edges { node { id ...Todo_todo } ...MarkAllTodosMutation_todoEdge } ...TodoListFooter_todoConnection } totalCount completedCount ...AddTodoMutation_user ...MarkAllTodosMutation_user ...Todo_user ...TodoListFooter_user } `, userRef, ); const commitAddTodoMutation = useAddTodoMutation(user, user.todos.__id); const handleOnSave = (text: string) => commitAddTodoMutation(text); const commitMarkAllTodosMutation = useMarkAllTodosMutation( user, user.todos.edges, ); const handleMarkAllChange = (e: SyntheticEvent<HTMLInputElement>) => { const complete = e.currentTarget.checked; commitMarkAllTodosMutation(complete); }; return ( <> <header className="header"> <h1>todos</h1> <TodoTextInput className="new-todo" onSave={handleOnSave} placeholder="What needs to be done?" /> </header> <section className="main"> <input checked={user.totalCount === user.completedCount} className="toggle-all" onChange={handleMarkAllChange} type="checkbox" /> <label htmlFor="toggle-all">Mark all as complete</label> <ul className="todo-list"> {user.todos.edges.map(({node}) => ( <Todo key={node.id} todoRef={node} userRef={user} todoConnectionId={user.todos.__id} /> ))} </ul> </section> <TodoListFooter userRef={user} todoConnectionRef={user.todos} /> </> ); }