loading...
Cover image for a first look at redwoodJS: part 4 - crud

a first look at redwoodJS: part 4 - crud

ajcwebdev profile image anthonyCampolo Updated on ・12 min read

What I’ve experienced and what I know many people have experienced learning React and getting into this is that path right now is very, very, very, very, very long. And hard. And horrible.

Tom Preston-Werner - Full Stack Radio 138

In part 1 we installed and created our first RedwoodJS application, in part 2 we created links to our different page routes and a reusable layout for our site, and in part 3 we got our database up and running and learned to create, retrieve, update, and destroy blog posts.

In this part we'll look at all the code that was generated that allowed us to perform our CRUD operations on the blog posts. We'll also set up our frontend to query data from our backend to render a list of our blog posts to the front page. If you've never worked with GraphQL or serverless functions like Lambda then some of the concepts in this part may be new.

If you want to learn more I have a post about the history of GraphQL, current projects, and resources.

4.1 api/src

We've seen the prisma folder under api, now we'll look at the src folder containing our GraphQL code. Redwood comes with GraphQL integration built in to make it easy to get our client talking to our serverless functions.

01-api-src-folder

4.2 graphql.js

The functions folder will contain any lambda functions your app needs in addition to the graphql.js file auto-generated by Redwood. This file is required to use the GraphQL API.

03-api-src-functions-graphql

We will be working more with the schema definition language and our services so you don't need to worry too much about what's going on in this file.

I still have no idea what the heck this thing is doing, all I know is it's doing some Apollo stuff. See these docs for further explanation.

4.3 posts.sdl.js

graphql contains your GraphQL schema. The files will end in .sdl.js. GraphQL schemas for a service are specified using the GraphQL SDL (schema definition language) which defines the API interface for the client.

Our schema has five object types each with their own fields and types.

05-api-src-graphql-posts-sdl<br>

Post - A blog post

06-api-src-graphql-posts-sdl-Post

Query - A query that retrieves either:

  • multiple posts in an array (line 12)
  • a single post with an id (line 13)

07-api-src-graphql-posts-sdl-Query

CreatePostInput - title and body input of new post

08-api-src-graphql-posts-sdl-CreatePostInput

UpdatePostInput - title and body input of updated post

09-api-src-graphql-posts-sdl-UpdatePostInput

Mutation - Create, update, or delete post

10-api-src-graphql-posts-sdl-Mutation

createPost

  • Takes title and body from CreatePostInput
  • Creates a Post

updatePost

  • Takes title and body from UpdatePostInput
  • Takes id of the updated Post

deletePost

  • Takes id of the deleted Post

4.4 db.js

lib contains one file, db.js, which instantiates the Prisma database client. You can use this folder for other code related to the API side that doesn't fit in functions or services.

Prisma Client is an auto-generated and type-safe query builder that's tailored to your data.

12-api-src-lib-db

4.5 posts.js

services contain business logic related to your data. A service implements the logic of talking to the third-party API.

This is where your code for querying or mutating data with GraphQL ends up. The difference is it's in a format that's reusable in other places in your application.

14-api-src-services-posts

Redwood will automatically import and map resolvers from the services file onto your SDL. You write resolvers in a way that makes them easy to call as regular functions from other resolvers or services.

Redwood will look in api/src/services/posts/posts.js for the following five resolvers:

posts

14-1-api-src-services-posts-posts

post

14-2-api-src-services-posts-post

createPost

14-3-api-src-services-posts-createPost

updatePost

14-4-api-src-services-posts-updatePost

deletePost

14-5-api-src-services-posts-deletePost

4.6 PostPage

PostPage is a component that takes in PostCell with a post's id as a prop. PostCell is wrapped in the PostsLayout component.

15-web-src-pages-PostPage

Here's the view of PostPage with a PostCell wrapped in the PostsLayout:

16-PostPage-rendered

4.7 PostsLayout

17-layouts-PostsLayout

If you click Posts you will be linked to routes.posts() and if you click New Post you will be linked to routes.NewPost()

Here's the view of just the PostsLayout:

18-PostsLayout-rendered

4.8 PostCell

Cells provide a simpler and more declarative approach to data fetching. When you create a cell you export several specially named constants and then Redwood takes it from there.

Cells should be used when your component needs some data from the database or other service that is delayed in responding. Redwood juggles what is displayed and when.

19-web-src-components-PostCell

The minimum you need for a cell are the QUERY and Success exports.

  • If you don't export an Empty component, empty results will be sent to your Success component.
  • If you don't provide a Failure component you'll get error output sent to the console.

4.9 Post

  • useFlash is an abridgment of React.useContext(FlashContext).
  • useMutation is a hook provided by Apollo which will allow us to execute the mutation when we're ready. It is the primary API for executing mutations in an Apollo application.

20-web-src-components-Post

DELETE_POST_MUTATION

GraphQL string representing the mutation that is passed into useMutation

21-web-src-components-Post-DELETE_POST_MUTATION

onCompleted

22-web-src-components-Post-onCompleted

Displays a message letting you know the post has been deleted

22-1-web-src-components-Post-onCompleted-rendered

onDeleteClick

23-web-src-components-Post-onDeleteClick

Asks you to confirm that you are sure you want to delete the post, and gives the id of the post about to be deleted

23-1-web-src-components-Post-onDeleteClick-rendered

rw-segment

In the return statement of the Post component there is a <div> with the className rw-segment which takes the post object and pulls out the post's id, title, body, and createdAt date.

24-web-src-components-Post-rw-segment

Here's the view in our application:

25-Post-rw-segment-rendered

rw-button-group

This code corresponds to the edit and delete buttons.

26-web-src-components-Post-rw-button-group

Here's the view in our application:

27-Post-rw-button-group-rendered

Now if we look at the entire component we can see how rw-segment and rw-button-group are nested inside empty tags.

28-web-src-components-Post-return

Here's the view for the entire component.

29-Post-return-rendered

4.10 NewPostPage

NewPostPage is a component that takes in NewPost wrapped in the PostsLayout component. The same PostsLayout from PostPage is being reused here but with a different component nested inside.

30-web-src-pages-NewPostPage

Here's the view:

31-NewPostPage-rendered

4.11 NewPost

NewPost is a component that takes in data from the PostForm component and uses CREATE_POST_MUTATION to save the post to the database.

32-web-src-components-NewPost

Here's the view:

33-new-post-form-rendered

4.12 PostForm

Redwood provides several helpers to make your life easier when working with forms. It is a wrapper around react-hook-form.

34-src-components-PostForm

onSubmit

A prop that accepts a function name or anonymous function to be called if validation is successful. Behind the scenes the handler given to onSubmit is given to react-hook-form's handleSubmit function.

35-src-components-PostForm-onSubmit

<Form>

Surrounds all form elements and provides contexts for errors and form submission.

36-src-components-PostForm

<FormError>

Displays an error message, typically at the top of your form, containing error messages from the server

37-src-components-PostForm-FormError

<Label>

Used in place of the HTML <label> tag and can respond to errors with different styling

38-src-components-PostForm-Title-Label

<TextField>

Renders an HTML field, but is registered with react-hook-form to provide some validation and error handling.

39-src-components-PostForm-Title-TextField

<FieldError>

Displays form validation errors and server errors.

40-src-components-PostForm-Title-FieldError

Here's the view:

41-Title-rendered

<Label>, <TextField>, and <FieldError> are also used for the Body.

42-Body

Here's the view:

43-Body-rendered

<Submit>

Used in place of <button type="submit"> and will trigger a validation check and "submission" of the form. It executes the function given to the onSubmit attribute on <Form>.

44-Save

Here's the view:

45-Save-rendered

And here's the view of the entire <Form> component:

46-PostForm-rendered

4.13 EditPostPage

Much like PostPage, EditPostPage is a component that takes in EditPostCell with a post's id as a prop. EditPostCell is wrapped in the PostsLayout component.

47-web-src-pages-EditPostPage

Here's the view:

48-EditPostPage-rendered

4.14 EditPostCell

We have the UPDATE_POST_MUTATION and QUERY object types we discussed at the beginning of this article. At the bottom we are again returning the <PostForm> component except this time we also have a post prop to specify which post is being edited.

49-web-src-components-EditPostCell

Here's the view:

50-EditPostCell-rendered

4.15 PostsPage

In Redwood we use singular "post" when working with a single post object and the data associated with it. When we are working with many posts we use the plural "posts." Here we are displaying all of our posts, so it's called PostsPage.

51-web-src-pages-PostsPage

Here's the view:

52-PostsPage-rendered

4.16 PostsCell

53-web-src-components-PostsCell

Here's the view if you have no posts:

54-posts-page

4.17 Posts

55-web-src-components-Posts

truncate limits the length of the posts being shown, and timeTag encapsulates the logic for created a timestamp for each post.

56-web-src-components-Posts-PostsList

onCompleted and onDeleteClick are the same functions that we saw in the NewPost component.

rw-table-wrapper-responsive

We have a div that wraps one big table with the className rw-table.

57-web-src-components-Posts-return

Here's the view:

58-Posts-rw-table-wrapper-responsive-rendered

This is a lot of code so we'll break this down to the table head and table body, and the table body is broken down into table posts and table actions.

  1. Table head (47-55)
  2. Table body (56-91)
  3. Table posts (57-62)
  4. Table actions (63-88)

59-Posts-rw-table-wrapper-responsive

<thead>

The table head lets us know the different fields.

60-Posts-thead

Here's the view:

61-Posts-thead-rendered

<tbody>

In the first half of the table body we map over the data passed through the post prop, use the post's id for the key and then pull out the id, title, body, and createdAt time.

62-Posts-td

Here's the view:

63-Posts-td-rendered

In the second half of the table body we have links to go to a post's page, edit a post, or delete a post.

64-Posts-rw-table-actions

Here's the view:

65-Posts-rw-table-actions-rendered

4.18 redwood generate cell

Now we are going to create a cell that will render the most recent blog posts to the front page.

yarn rw g cell BlogPosts
Enter fullscreen mode Exit fullscreen mode

Redwood will generate a file called BlogPostsCell.js and a file for testing called BlogPostsCell.test.js.

67-generating-cell-files

This will generate a QUERY for us and use JSON.stringify to render the results of the query. But there is one thing we need to change.

68-web-src-components-BlogPostsCell

We need to make a slight adjustment to get our QUERY to match up with the schema that we have already created. Change blogPosts on lines 3, 15, 16 to just posts.

69-web-src-components-BlogPostsCell-posts-edit

Now we can take the BlogPostsCell component and insert it into our HomePage component. We need to first import it, and then place the tag inside of the BlogLayout tags.

70-BlogPostsCell-in-HomePage

This gives us just the id and the typename which is Post.

71-BlogPostsCell-render-HomePage

Lets go back to our QUERY and add in title, body, and createdAt.

72-web-src-components-BlogPostsCell-id-title-body-createdAt

Now we should get all the info we need on the home page.

73-BlogPostsCell-render-id-title-body-createdAt

This doesn't look very good though, I don't think anyone would want to read this blog.

In the BlogPostsCell file inside Success we can create a component for our posts and give it a little structure.

74-BlogPostsCell-map-over-posts

We'll do some more styling later on but for now we have our posts rendered to the front page.

75-BlogPostsCell-render-map-over-posts

In the next part we'll create a contact form.

Posted on by:

Discussion

pic
Editor guide