- 
      
- 
        Save amarg26/bcca1dcbf0e9699110ad7f33ca2fb22a to your computer and use it in GitHub Desktop. 
Revisions
- 
        ahandsel revised this gist Aug 19, 2021 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ <!-- 00_React_Workshop_v3.md --> # React & REST API Workshop Version 3 ## Let's POST Data to a Web Database From a React Component 
- 
        ahandsel revised this gist Aug 19, 2021 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,2 +0,0 @@ 
- 
        ahandsel revised this gist Aug 19, 2021 . 13 changed files with 1051 additions and 1 deletion.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,2 @@ .DS_Store This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,88 @@ <!-- 00_React_Workshop_v2.md --> # React & REST API Workshop Part 2 ## Let's POST Data to a Web Database From a React Component Thank you for attending our 2nd **Kintone x React** workshop! Use the following files to follow along! ### Download Links Click [**here**](https://gist.github.com/ahandsel/556e42aad59ff22604a9042174c556bc/archive/master.zip) or the  button on the upper right corner for all the code & slides you need for our workshop! --- ## Outline * [📎 PREREQUISITE](#-prerequisite) * [💾 Install Node & npm](#-install-node--npm) * [🕹️ Install a Sample React App](#️-install-a-sample-react-app) * [🚀 Getting your FREE Kintone Database](#-getting-your-free-kintone-database) * [📺 Quick Videos Going Over the Prep Work](#-quick-videos-going-over-the-prep-work) * [📚 Suggested Reading](#-suggested-reading) * [Details at dev.to](#details-at-devto) * [Overview of the Workshop](#overview-of-the-workshop) --- ## 📎 PREREQUISITE ### 💾 Install Node & npm * Node ≥ 10.16 and npm ≥ 5.6 are required for this workshop * Confused? 🤔 → Check out the [Video Guides](#-quick-videos-going-over-the-prep-work) ### 🕹️ Install a Sample React App * Create a `myproject` folder * We will be starting from the publicly available [sample React App](https://create-react-app.dev/). * Confused? 🤔 → Check out the [Video Guides](#-quick-videos-going-over-the-prep-work) ### 🚀 Getting your FREE Kintone Database #### ① Sign-Up for Developer Program Account (Website) 🌐 * [bit.ly/KDP_signup](https://bit.ly/KDP_signup) * ⚠ Do NOT use Safari * ⚡Accept Cookies First * ✅ Use Chrome & Firefox #### ② THEN Create a Kintone Subdomain (Database) 📂 * [bit.ly/K_DevLic](http://bit.ly/K_DevLic) * ⚡ Only use lowercase, numbers, & hyphens in your subdomain * ⚠ Do not use uppercase nor special characters Confused? 🤔 → Check out the [Video Guides](#-quick-videos-going-over-the-prep-work) --- ### 📺 Quick Videos Going Over the Prep Work | Install Node & Sample React App | Signing Up for Kintone | | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | [](https://youtu.be/4Kw-i_rX3tY) <https://youtu.be/4Kw-i_rX3tY> | [](https://youtu.be/Gzz8SbTuoFg) <https://youtu.be/Gzz8SbTuoFg> | --- ## 📚 Suggested Reading We advise you to have a look through the following React documents beforehand: 1. [Hello World](https://reactjs.org/docs/hello-world.html) 2. [Introducing JSX](https://reactjs.org/docs/introducing-jsx.html) 3. [Rendering Elements](https://reactjs.org/docs/rendering-elements.html) 4. [Components and Props](https://reactjs.org/docs/components-and-props.html) ## Details at [dev.to](https://dev.to/will_yama/series/11707) [](https://dev.to/will_yama/series/11707) Check out Will's [React & REST API Series' Articles](https://dev.to/will_yama/series/11707) at [dev.to](https://dev.to/will_yama/series/11707) Community 👩💻👨💻! --- ## Overview of the Workshop | Parts | Type | Description | | ------------------------------------------------------------------------------------------------------- | --------------- | ------------------------------------------------ | | [Prep](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-01_prep-md) | Setup Guide | Everything you need to do before the workshop | | [Part A](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-a_promiseerror_demo-md) | Demo | Quick demo using promises in React | | [Part B](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-b_hooks-md) | **Live Coding** | Let's use `useState` & `useEffect` Hooks instead | | [Part C](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-c_kintonedatabase-md) | Setup Guide | Create a Kintone account & a database app | | [Part D](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-d_cors_error_demo-md) | Demo | Quick demo that results in CORS error | | [Part E](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-e_expressserver-md) | Setup Guide | Let's install the *backend* Express server | | [Part F](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-f_get_data-md) | Demo | Getting data from the Kintone App | | [Part G](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-g_post_data-md) | **Live Coding** | Posting data to the Kintone App | This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,179 @@ # Prepping for React Workshop This is a step-by-step guide that will go over everything you need to do before our workshop in detail! Let's get started! **Outline**: * [1. Create a `myproject` folder](#1-create-a-myproject-folder) * [Check if you already have Node.js or npm](#check-if-you-already-have-nodejs-or-npm) * [2. Install Node.js](#2-install-nodejs) * [macOS with nodenv](#macos-with-nodenv) * [Windows with nvm-windows](#windows-with-nvm-windows) * [3. Install a Sample React App](#3-install-a-sample-react-app) * [⚠️ Got an error?](#️-got-an-error) * [📺 YouTube Quick Videos Going Over the Node Install & Create-React-App](#-quick-videos-going-over-the-node-install--create-react-app) --- ## 1. Create a `myproject` folder Somewhere inside your Document folder will be good. ### Check if you already have Node.js or npm React requires **Node ≥ 10.16** & **npm ≥ 5.6** Go **inside** the `myproject` folder. ```shell $ node -v $ npm -v ``` --- ## 2. Install Node.js If Node & npm are missing, let's install them! **Options**: * [macOS with nodenv](#macos-with-nodenv) * [Windows with nvm-windows](#windows-with-nvm-windows) ### macOS with [nodenv](https://github.com/nodenv/nodenv) We recommend installing Node.js using [nodenv](https://github.com/nodenv/nodenv) to manage node versions. This allows your computer to have a specific Node.js version per project. ⚠️ Remove any existing installations of Node.js before installing nodenv! ⚠️ Having different Node.js installations can lead to conflict issues. **Step 1**: Install nodenv with [Homebrew](https://brew.sh/) * Update Homebrew: ```shell brew update && brew upgrade ``` * Install nodenv: ```shell brew install nodenv ``` **Step 2**: Set up nodenv shell integration * Run the initialization command: ```shell nodenv init ``` * Do as instructed by appending the following line into your shell's rc/profile file: ```shell eval "$(nodenv init -)" ``` * For Zsh users: ```shell $ echo 'eval "$(nodenv init -)"' >> ~/.zshrc $ cat < ~/.zshrc ``` * For Bash users: ```shell $ echo 'eval "$(nodenv init -)"' >> ~/.bash_profile $ cat < ~/.bash_profile ``` **Step 3**: Implement the changes Close & open a new Terminal window for the changes to take place. Optional: Verify that nodenv is properly set up using [nodenv-doctor](https://github.com/nodenv/nodenv-installer/blob/master/bin/nodenv-doctor) script. * For those using Z shell (Zsh) shell: ```shell curl -fsSL https://github.com/nodenv/nodenv-installer/raw/master/bin/nodenv-doctor | bash ``` * Expected result: ```shell Checking for `nodenv' in PATH: /usr/local/bin/nodenv Checking for nodenv shims in PATH: OK Checking `nodenv install' support: /usr/local/bin/nodenv-install (node-build 3.0.22-4-g49c4cb9) Counting installed Node versions: none There aren't any Node versions installed under `~/.nodenv/versions'. You can install Node versions like so: nodenv install 2.2.4 Auditing installed plugins: OK ``` **Step 4**: Install Node.js inside the React Workshop folder (`myproject`) * Now you're ready to install specific Node.js versions! * **Inside** `myproject` folder, install Node.js version `14.5.0`: ```shell $ cd myproject/ $ nodenv install 14.5.0 $ nodenv local 14.5.0 ``` Alright! Your Mac is now armed with Node.js! Skip down to the [3. Install a Sample React App](#3-install-a-sample-react-app) section! --- ### Windows with [nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) The following steps are straight from the Microsoft Docs on [Set up NodeJS on native Windows](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-windows). We recommend installing and managing Node.js with [nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) ⚠️ Remove any existing installations of Node.js before installing nvm-windows! ⚠️ Having different Node.js installations can lead to conflict issues. **Step 1**: Go to the [windows-nvm's latest release](https://github.com/coreybutler/nvm-windows/releases). **Step 2**: Download the **nvm-setup.zip** file for the most recent release. **Step 3**: Once downloaded, open the zip file, then open the **nvm-setup.exe** file. **Step 4**: The Setup-NVM-for-Windows installation wizard will walk you through the setup steps, including choosing the directory where both nvm-windows and Node.js will be installed. *  **Step 5**: After the installation is complete, open PowerShell & enter `nvm ls` * `nvm ls` lists out installed Node versions (should be none at this point) *  **Step 6**: Install Node.js inside the React Workshop folder (`myproject`) * Now you're ready to install specific Node.js versions! * Inside `myproject` folder, install Node.js version `14.5.0`: ```powershell $ cd .\Documents\myproject $ nvm install 14.5.0 $ nvm use 14.5.0 ``` Alright! Your Windows is now armed with Node.js! Skip down to the [3. Install a Sample React App](#3-install-a-sample-react-app) section! --- ## 3. Install a Sample React App Still inside the `myproject` folder, let's install a React App named `frontend`. Install: * `npx create-react-app frontend` Starting it up: * Go **inside** the `frontend` folder * `npm start` ## ⚠️ Got an error? * Make sure you are **inside** the `myproject` folder when setting up Node.js * Mac: `nodenv local 14.5.0` * Windows: `nvm use 14.5.0` * Make sure you are **inside** the `frontend` folder when running `npm start`! ##  Quick Videos Going Over the Node Install & Create-React-App <p align="center"> <a href="https://youtu.be/4Kw-i_rX3tY"> <img height="200" alt="Installing Node.js & Create a New React App YouTube Thumbnail" src="https://img.youtube.com/vi/4Kw-i_rX3tY/mqdefault.jpg"> </a> </p> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,47 @@ # Part A: Using Promises in React When getting data from an API call, we usually need to use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises), right? So let's try that in our frontend React App. --- ## Sample Code for App.js Here is an example that tries to output an API response in the frontend React App. It calls [Random User Generator API](https://randomuser.me/api/), waits for a response, and then creates a React element using the JSON data. Let's see what happens! File Location: `.../myproject/frontend/src/App.js` ```jsx import React from 'react'; // Call Random User Generator API const restEndpoint = 'https://randomuser.me/api/'; // Wait for response & tries to output it to React async function App() { const response = await fetch(restEndpoint); const jsonResponse = await response.json(); console.log(jsonResponse); // React.createElement( type, [properties], [...children]); return React.createElement('h1', null, JSON.stringify(jsonResponse)); }; export default App; ``` --- ## Result - Error The `App()` function component returns a promise object immediately as it waits for the Random User Generator API's response. React doesn't "wait" for the REST API result, so it tries to create and render the element with the promise object immediately and failing. It attempts to display the Random User Generator API response into a React element. However, the following error will display instead: ```text Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. ```  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,69 @@ # Part B: Using Hooks in React! We will use `useState` & `useEffect` Hooks to handle the REST API calls in React. --- ## What is `useState` & `useEffect` Hooks [useState hooks](https://reactjs.org/docs/hooks-state.html) allow us to use special "state" variables that we can utilize to render into the React UI. [useEffect hooks](https://reactjs.org/docs/hooks-effect.html) allow us to run functions after the rendering has finished. We'll use this to run a REST API call and update the state variable, which will then cause React to re-render the UI. ## Sample Code for App.js File Location: `.../myproject/frontend/src/App.js` ```jsx // Get started by importing the React JavaScript library & Hooks import React, { useState, useEffect } from 'react'; // Call Random User Generator API const restEndpoint = 'https://randomuser.me/api/'; // Wait for response & tries to output it to React // async function App() { async function callRestApi() { const response = await fetch(restEndpoint); const jsonResponse = await response.json(); console.log(jsonResponse); return JSON.stringify(jsonResponse); }; function App() { // Establish useState by giving it our initial state // const [state, setState] = useState(initialState); const [apiResponse, setApiResponse] = useState('*** now loading ***'); // useEffect takes 2 arguments: // 1st = a function, called effect, that is executed when the React Component is rendered // 2nd = Array of dependencies to control when effect is to be executed after mounting the component; Empty array = only invoke effect once useEffect(() => { callRestApi().then( result => setApiResponse(result)); }, []); return ( // JSX includes html-like syntax <div> <h1>React App</h1> <p>{apiResponse}</p> </div> ); }; export default App; ``` --- ## Result - Success Expected output: Outputs the Random User API Call to the frontend React App.  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,36 @@ # Kintone Database Solution *Built for teamwork, designed by you* ## 🚀 Getting your FREE Kintone Database ### ① Sign-Up for Developer Program Account (Website) 🌐 * [bit.ly/KDP_signup](https://bit.ly/KDP_signup) * ⚠ Do NOT use Safari * ⚡Accept Cookies First * ✅ Use Chrome & Firefox ### ② THEN Create a Kintone Subdomain (Database) 📂 * [bit.ly/K_DevLic](http://bit.ly/K_DevLic) * ⚡ Only use lowercase, numbers, & hyphens in your subdomain * ⚠ Do not use uppercase nor special characters Confused? 🤔 → Check out the video below: ### 📺 Sign up for Kintone Developer Program & Developer License [](https://youtu.be/Gzz8SbTuoFg) <https://youtu.be/Gzz8SbTuoFg> ## Create a Kintone App Let's create a Kintone App to list off your favorite [Manga](https://en.wikipedia.org/wiki/Manga)s! Here are the **required** fields & their **configurations** for our workshop: | Field Type | Field Name | Field Code | Note | | ------------- | ------------- | ---------- | --------------------------------- | | Text | Title | `title` | The manga's title | | Text | Author | `author` | The manga's author | | Record number | Record number | `recordID` | Auto generated IDs for each entry |  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,62 @@ # Part D: CORS Error Demo Now that we are outputting Random User Generator API's response onto our frontend React App let's output more useful results! Using Kintone's low-code Database platform, we can easily create & host a database that is accessible with REST APIs. But can we just swap the request endpoint with Kintone's? --- ## Sample Code for App.js We will try a GET request to Kintone from our frontend React App. If you want to run this code, be sure to input your Kintone specifications for `subdomain`, `appID`, and `apiToken`. File Location: `.../myproject/frontend/src/App.js` ```jsx import React, { useState, useEffect } from 'react'; // Kintone API Setup const subdomain = ''; //Enter your Kintone Subdomain (ex: devevents) const appID = ''; //Enter your App's ID number (ex: 1) const apiToken = ''; //Enter your App's API Token const getKintoneData = async () => { const requestEndpoint = `https://${subdomain}.kintone.com/k/v1/records.json?app=${appID}`; const fetchOptions = { method: 'GET', headers: { 'X-Cybozu-API-Token': apiToken } }; const response = await fetch(requestEndpoint, fetchOptions); const jsonResponse = await response.json(); console.log(jsonResponse); return JSON.stringify(jsonResponse); }; function App() { const [apiResponse, setApiResponse] = useState('*** now loading ***'); useEffect(() => { getKintoneData().then( result => setApiResponse(result)); }, []); return ( <div> <h1>React App</h1> <p>{apiResponse}</p> </div> ); }; export default App; ``` --- ## Result - CORS Error [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) Error occurs since we cannot access the resources that lie on Kintone's domain directly from our domain (frontend React App).  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,83 @@ # Installing the Express Server (backend) **Outline** * [What is Express?](#what-is-express) * [Installing the Express Server](#installing-the-express-server) * [Starting the Express Server](#starting-the-express-server) * [Debugging](#debugging) ## What is Express? [Express](https://expressjs.com/) is a backend web application framework for Node. We will use Express to create custom endpoints that our frontend React App can make calls to. When we make requests to these custom endpoints, the Express server will make REST API calls to our desired 3rd party service endpoint, receive the response, and then route the response back to our frontend React App. ## Installing the Express Server (1) From your terminal, go to your **myproject** folder ```bash cd .../myproject ``` (2) Create **backend** folder ```bash mkdir backend cd backend ``` (3) Create your Express project ```bash npm init ``` * Hit enter to skip the questions (4) Continue to install some dependencies ```bash npm install express node-fetch cors ``` (5) Create a **server.js** file inside the **backend** folder ```bash touch server.js ``` ## Starting the Express Server (1) Configure the **server.js** file (2) From your terminal, go to your **backend** folder ```bash cd .../myproject/backend ``` (3) Start the Express Server ```bash node server.js ``` --- ## Debugging No response when starting the Express server? * Make sure you are inside the `backend` folder when starting the Express server Got a `UnhandledPromiseRejectionWarning` error? ```text (node:5379) UnhandledPromiseRejectionWarning: FetchError: request to https://.kintone.com/k/v1/records.json?app= failed, reason: getaddrinfo ENOTFOUND .kintone.com ``` * Looks like Kintone API credentials are missing * Be sure to enter your Subdomain, App ID, and API Token under the `Kintone API Setup` section in `server.js` Got a `GAIA_IA02` error? * Enter the App's API Token in `apiToken` * Be sure to hit the `save` button & the `Update App` button to implement the API Token change. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,156 @@ # Part F: GET data from the Kintone App Let's grab data from the Kintone Database App and output it to our frontend React App! To implement the GET request, we will be creating the following files: * [backend - server.js](#backend---serverjs) * [frontend](#frontend) * [getList.js](#getlistjs) * [App.js](#appjs) --- ## backend - server.js We will set up an Express server that calls Kintone on behalf of the frontend React App to avoid the CORS error. Expected result: * Calls Kintone's GET Records API when <http://localhost:5000/getData> endpoint is requested with a GET request * Returns the JSON response to frontend React App (<http://localhost:3000>) File Location: `.../myproject/backend` ```js // backend - server.js // Express Server Setup const express = require('express'); const cors = require('cors'); const fetch = require('node-fetch'); const PORT = 5000; const app = express(); // Parse incoming requests with JSON payloads app.use(express.json()); // Set Cross-Origin Resource Sharing (CORS) to frontend React App app.use(cors()); const corsOptions = { origin: 'http://localhost:3000' }; // Kintone API Setup const subdomain = ''; //Enter your Kintone Subdomain (ex: devevents) const appID = ''; //Enter your App's ID number (ex: 1) const apiToken = ''; //Enter your App's API Token (ex: cJrAD9...) // Append a Query Parameters to the Request Endpoint const parameters = 'query=order by recordID asc'; // Call Kintone's GET Records API const multipleRecordsEndpoint = `https://${subdomain}.kintone.com/k/v1/records.json?app=${appID}&${parameters}` // This runs if a GET request calls for localhost:5000/getData app.get('/getData', cors(corsOptions), async (req, res) => { const fetchOptions = { method: 'GET', headers: { 'X-Cybozu-API-Token': apiToken } } const response = await fetch(multipleRecordsEndpoint, fetchOptions); const jsonResponse = await response.json(); res.json(jsonResponse); }); app.listen(PORT, () => { console.log(`Example app listening at http://localhost:${PORT}`); }); ``` --- ## frontend Now that we got our Express server setup, time for configuring the frontend React App! Expected Result: Data from the Kintone App will be outputted as bullet points at <http://localhost:3000/>. ### getList.js First, we will create a `requests` folder inside the `frontend/src/`. This is where we will add the two functions that interacts with React and Kintone. In `getList.js`, we will create a list array by looping through Kintone's response. **Kintone API Notes**: * `record.title.value` is the value of the Title field * `record.author.value` is the value of the Author field **React Note**: * When creating a list in React, assign an unique ID to each item * We will use `record.recordID.value` for the keys File Location: `.../myproject/frontend/src/requests/getList.js` ```jsx // getList.js - Create a list array // Declare the GET endpoint defined in our Express server const getRecordsEndpoint = "http://localhost:5000/getData"; export default async function getList() { const response = await fetch(getRecordsEndpoint); const jsonResponse = await response.json(); console.log(jsonResponse); const arrayOfLists = jsonResponse.records.map( record => <li key={record.recordID.value}><b>{record.title.value}</b> written by {record.author.value}</li> ) return arrayOfLists; }; ``` ### App.js We will be importing the `getList` module for the Kintone records-based list items. File Location: `.../myproject/frontend/src/App.js` ```jsx // App.js - Parent Component import React, { useState, useEffect } from 'react'; import getList from './requests/getList.js'; // Used to get Kintone data function App() { const [listItems, setListItems] = useState('*** now loading ***'); useEffect(() => { getList().then( result => setListItems(result) ); }, []); return ( <div> <div> <h1>React Manga List App</h1> <ul>{listItems}</ul> </div> </div> ); } export default App; ``` --- ## Result - Kintone Database App's data displayed as bullet points Here is what it looks like when displaying our Manga DB App. It lists out our favorite Japanese comics, ordered by `recordID`.  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,258 @@ # Part G: POST data to the Kintone App Now that we can retrieve & display the data from the Kintone Database App let's submit new data via our frontend React App! We will do this by adding a POST request route on the Express server used when the user inputs via the form on the frontend React App. To implement the POST request, we will be creating the following files: * [backend - server.js](#backend---serverjs) * [frontend](#frontend) * [getList.js](#getlistjs) * [postRecord.js](#postrecordjs) * [InputForm.js](#inputformjs) * [App.js](#appjs) **Note** Be sure to restart your Express server when updating `server.js`. * `Control` + `C` to end the Express server * `node server.js` to start it up again ## backend - server.js We will add another endpoint to make our POST requests. Expected result: * When `localhost:5000/getData` endpoint is called, a GET request is sent to Kintone for data retrieval. * When `localhost:5000/postData` endpoint is called, a POST request is sent to Kintone to update the database with the submitted entry. File Location: `.../myproject/backend` ```js // backend - server.js // Express Server Setup const express = require('express'); const cors = require('cors'); const fetch = require('node-fetch'); const PORT = 5000; const app = express(); // Parse incoming requests with JSON payloads app.use(express.json()); // Set Cross-Origin Resource Sharing (CORS) to frontend React App app.use(cors()); const corsOptions = { origin: 'http://localhost:3000' }; // Kintone API Setup const subdomain = ''; //Enter your Kintone Subdomain (ex: devevents) const appID = ''; //Enter your App's ID number (ex: 1) const apiToken = ''; //Enter your App's API Token (ex: cJrAD9...) // Append a Query Parameters to the Request Endpoint const parameters = 'query=order by recordID asc'; // Call Kintone's GET Records API const multipleRecordsEndpoint = `https://${subdomain}.kintone.com/k/v1/records.json?app=${appID}&${parameters}` // Call Kintone's GET Record API const singleRecordEndpoint = `https://${subdomain}.kintone.com/k/v1/record.json?app=${appID}&${parameters}`; // This runs if a GET request calls for localhost:5000/getData app.get('/getData', cors(corsOptions), async (req, res) => { const fetchOptions = { method: 'GET', headers: { 'X-Cybozu-API-Token': apiToken } } const response = await fetch(multipleRecordsEndpoint, fetchOptions); const jsonResponse = await response.json(); res.json(jsonResponse); }); // Add a New Route for a POST request using singleRecordEndpoint // This runs if a POST request calls for localhost:5000/postData app.post('/postData', cors(corsOptions), async (req, res) => { const requestBody = { 'app': appID, 'record': { 'title': { 'value': req.body.title }, 'author': { 'value': req.body.author } } }; const options = { method: 'POST', headers: { 'X-Cybozu-API-Token': apiToken, 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody) } const response = await fetch(singleRecordEndpoint, options); const jsonResponse = await response.json(); res.json(jsonResponse); }); app.listen(PORT, () => { console.log(`Example app listening at http://localhost:${PORT}`); }); ``` ## frontend We will add a form for user input and function to make a POST request on our newly defined Express server's endpoint. Expected result: * Display Kintone app data as a clean list * Form at the bottom to add user input * When an input is submitted, a POST request is sent out & the list is updated ### getList.js `getList.js` will be the same as shown in [Part F](https://gist.github.com/ahandsel/813e642bf36008192708c50a23185935#file-f_get_data-md). File Location: `.../myproject/frontend/src/requests/getList.js` ### postRecord.js Similar to `getList.js`, we will add `postRecord.js` in the `requests` folder to handel the Kintone POST API calls. ```jsx // postRecord.js - Post to Kintone // Declare the GET & POST endpoints defined in our Express server const addRecordEndpoint = "http://localhost:5000/postData"; // Make REST API Calls & take in the values stored in the state variables related to the input fields export default async function postRecord(title, author) { const recordBodyParameters = { 'title': title, author // ES6 syntax that functions the same as above } const options = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(recordBodyParameters) } const response = await fetch(addRecordEndpoint, options); const jsonResponse = await response.json(); console.log(JSON.stringify(jsonResponse)); return jsonResponse; }; ``` ### InputForm.js We will now create a React component that appends a form on our React App. Create a `components` folder in the `src` folder. This is where we will create `InputForm.js`. We will import two files in the `requests` folder to make GET & POST API calls to Kintone. We will create and export the form component. File Location: `.../myproject/frontend/src/components/InputForm.js` ```jsx // InputForm.js - Create a form that makes a POST request import { useState } from 'react'; import getList from '../requests/getList.js'; import postRecord from '../requests/postRecord.js'; function InputForm(props) { const [title, setTitle] = useState(""); const [author, setAuthor] = useState(""); function buttonClick(title, author) { postRecord(title, author) .then(() => getList()) // Trigger re-rendering the getList .then(result => props.setListItems(result)) } function handleTitleChange(event) { setTitle(event.target.value); } function handleAuthorChange(event) { setAuthor(event.target.value); } return ( <div> <form> <div> <label>Title: </label> <input type="text" value={title} onChange={andleTitleChange} /> </div> <div> <label>Author: </label> <input type="text" value={author} onChange={handleAuthorChange} /> </div> <button type="button" onClick={() => buttonClick(title, author)}>Post to Kintone</button> </form> </div> ); }; export default InputForm; ``` ### App.js For the form component, we will import `InputForm`. We will add the InputForm in the div we are exporting. For the GET API call function, we will import `getList`. File Location: `.../myproject/frontend/src/App.js` ```jsx // App.js - Parent Component import React, { useState, useEffect } from 'react'; import getList from './requests/getList.js'; // Get the form component import InputForm from './components/InputForm.js' function App() { const [listItems, setListItems] = useState('*** now loading ***'); useEffect(() => { getList().then( result => setListItems(result) ); }, []); return ( <div> <div> <h1>React Manga List App</h1> <ul>{listItems}</ul> </div> <InputForm setListItems={setListItems} /> </div> ); } export default App; ``` ## Result - Kintone Database App's data displayed as bullet points with a form to submit a new entry  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,50 @@ # Troubleshooting Notes ## Starting the frontend React Project Enter the following commands in your terminal * $ `cd ../myproject/frontend` * $ `npm start` Then access your React project at * `http://localhost:3000/` ## Starting the backend Express Server Enter the following commands in your terminal * $ `cd ../myproject/backend` * $ `node server.js` Then access your Express server at * `http://localhost:5000/` Access the Kintone API call at * `http://localhost:5000/getData` ## Kintone Section: React not updating after updating server.js Be sure to restart the server after making changes to server.js! (1) Go to the terminal running the Express server. It should look something like this: ```shell user@computer backend % node server.js Example app listening at http://localhost:${PORT} ``` (2) Restart the Express server * Stop the server: `ctrl + c` * Start the server: $ `node server.js` (3) Reload the browser showing the React App. * `http://localhost:3000/` ## Kintone API Token To generate an API Token for a Kintone App: 1. Go to the Kintone App 2. Go to the Gear icon ⚙️ (top right corner) > Open the App Settings page 3. Click on the **App Settings** Tab > Click on **API Token** settings 4. Click the `Generate` button to generate a token 5. Click the `Save` button (top left corner) to save the token setting 6. Finally, click the `Update App` button (top right corner) to implement the token setting change.  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,21 @@ # Thank you for attending our workshop! ## Your Feedback Please 🙇 Please fill out this quick survey for a chance to win 💰️ $25 Amazon Gift Card: <!-- BeMyApp's --> ## [bit.ly/KDP_Q](http://bit.ly/KDP_Q) ↢ ## Next Step For those wanting a visualization projects: * Try linking to different [amChart libraries](https://www.amcharts.com/demos/), and reuse the code we used in the workshop! For those wanting to create projects on Kintone and want to retrieve & store data from public APIs: * Call [public APIs](https://github.com/public-apis/public-apis#index) from Kintone! For those wanting to use Kintone as a back-end database: * Check out [Deploy a REST API calling node.js App to Heroku](https://dev.to/will_yama/deploy-a-rest-api-calling-node-js-app-to-heroku-2mia) tutorial! ## Where to Get Help? * [Kintone Developer Community forum](https://developer.kintone.io/hc/en-us/community/posts) * [Stack Overflow](https://stackoverflow.com/) 
- 
        ahandsel created this gist Aug 19, 2021 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ _