使用 React Context, Hooks, Immer, Golang 建立一個TodoList

clipboard.png

背景

上週末在家沒啥事, 想寫點東西,一時不知道寫什麼好。 而後就想起來一個去了Airbnb 的同窗, 說Airbnb 的面試風格是以實操爲主,她面了8輪, 輪輪都是寫代碼(2018年), 使人十分懼怕。 html

代碼題目都不是很難, 簡單分享幾道題:前端

clipboard.png

而後我就看到了實現一個Todo Listreact

這種題目不難, 可是靈活度很高, 沒有什麼限制條件, 你隨意發揮, 能夠從多方面考察候選人。git

就拿這道題下手吧, 開造。github

[ 文末有本文所有的源代碼, 經過這個例子, 你會了解 React ContextHooks 的使用方式, 以及 如何使用 Golang 編寫 CURD Api]golang

廢話很少說了,進入正題。web

功能實現

首先就是新建一個項目, 不限工具, CRA 什麼的均可以, 我就用了以前本身寫的一個工具, 簡單起了項目, 不過這些都無所謂了, 直接上代碼:面試

// index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';

ReactDOM.render(<App />, document.getElementById('root'));

App

// App.js

import React from "react";
import { TodosProvider } from './Store'
import { TodoList } from './TodoList'

const App = () => {
  return (
    <TodosProvider>
      <TodoList />
    </TodosProvider>
  );
}

export default App

Store

這裏我建立了兩個Context, 一個用於存儲數據, 另外一個用於更新數據。數據庫

例如:後端

const initialState = []

const StateContext = React.createContext(initialState)
const UpdateContext = React.createContext(null)

被 Context 包裹的組件能夠取用這些傳入的值。

完整代碼:

// Store.js
import React from 'react'
import produce from 'immer'

// An array of todos, where a todo looks like this: 
// { id: string; title: string; isCompleted: boolean }
const initialTodos = [{
  id: 1,
  title: "One",
  isCompleted: false
}, {
  id: 2,
  title: "Two",
  isCompleted: false
}, {
  id: 3,
  title: "Three",
  isCompleted: false
}]

const StateContext = React.createContext(initialTodos)
const UpdateContext = React.createContext(null)

export function TodosProvider({ children }) {
  const [todos, updateTodos] = React.useReducer(produce, initialTodos)
  return (
    <UpdateContext.Provider value={updateTodos}>
      <StateContext.Provider value={todos}>
        {children}
      </StateContext.Provider>
    </UpdateContext.Provider>
  )
}

export function useTodos() {
  return [React.useContext(StateContext), React.useContext(UpdateContext)]
}

Todo主體

這裏的實現也很簡單,我先簡單作了兩個小功能, 一個是完成某一項, 一個是刪除某一項, 完整代碼:

// TodoList
import React from 'react';
import { useTodos } from './Store'

export function TodoList() {
  const [todos, updateTodos] = useTodos()

  const deleteTodo = id => updateTodos(todos => {
    const todoIdxToDelete = todos.findIndex(todo => todo.id === id)
    todos.splice(todoIdxToDelete, 1)
  })

  const completeTodo = id => updateTodos(todos => {
    todos.find(todo => todo.id === id).isCompleted = true
  })

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id} style={todo.isCompleted ? { color: 'red' } : { color: 'green' }}>
          <span>{todo.title}</span>
          <button onClick={() => deleteTodo(todo.id)}>Delete</button>
          <button onClick={() => completeTodo(todo.id)}>Complete</button>
        </li>
      ))}
    </ul>
  )
}

DEMO:

clipboard.png

下面把新增也一塊兒作了。

想着都已經作到這一步了, 數據一刷新就沒了, 乾脆存到數據庫裏吧, 最終的樣子:

clipboard.png

後端接口實現:

看下這幾個CURD接口是怎麼寫的:

Api: C

clipboard.png


Api: U

clipboard.png

Api: R

clipboard.png

Api: D

clipboard.png

代碼都比較簡單, 一眼就能看明白是作什麼的, 就很少作解釋了。

後端完整的代碼在這裏:

https://github.com/beMySun/go...

前端部分完整的代碼在這裏:
https://github.com/beMySun/re...

數據庫用的 mySql, 建庫, 加改表能夠用這個Sequel Pro, 很方便

clipboard.png

若是不想用這個, 也能夠用命令行工具來操做。

再貼幾個會用的命令吧:

show databases;

clipboard.png

use database;

clipboard.png

describe todos_tab;

clipboard.png

select * from todos_tab limit 10;

clipboard.png

加一個字段:text

clipboard.png

加一個字段:isCompleted

clipboard.png

最後

功能很簡單, 可是作的時候須要考慮的東西仍是不少的。

若是有朋友也想學習下, 能夠把代碼下載下來本身運行跑一下。

後端完整的代碼在這裏:
https://github.com/beMySun/go...

前端部分完整的代碼在這裏:
https://github.com/beMySun/re...

這個後端的demo 包含了完整的CURD, 是一個很好的學習demo, 但願對你們的學習有所幫助。

才疏學淺, 行文不免有紕漏。

如有錯誤, 歡迎指正,謝謝。

以上。

clipboard.png

若是本文對你有幫助, 別忘了點贊呦~

參考資料:
https://learnku.com/golang/t/...
https://gorm.io/docs/update.h...

相關文章
相關標籤/搜索