实战!增删改查的不平凡

简介: 结合 React 哲学 中的思想,我们可以很自然的想到该按钮中的数据有:// 任务列表const [jobs, setJobs] = useState<Array<Job>>([])// 编辑窗口显示与否const [show, setShow] = useState(false)// 每次输入时当前任务描述const [desc, setDesc] = useState('')单个任务的数据格式为interface Job { desc: string, id: string, createTime: number, isSelected: boolean}

微信图片_20220511163416.png


学习了 useState 与 useRef ,结合前面几章内容,我们可以实现一个非常经典的功能:任务列表。


当我点击新增时,编辑弹窗出现,输入框自动获得焦点


微信图片_20220511163422.png


输入任务描述之后,点击创建,此时任务创建成功,编辑弹窗消失,新增按钮再次出现


微信图片_20220511163426.png


结合 React 哲学 中的思想,我们可以很自然的想到该按钮中的数据有:


// 任务列表
const [jobs, setJobs] = useState<Array<Job>>([])
// 编辑窗口显示与否
const [show, setShow] = useState(false)
// 每次输入时当前任务描述
const [desc, setDesc] = useState('')


单个任务的数据格式为


interface Job {
  desc: string,
  id: string,
  createTime: number,
  isSelected: boolean
}


点击「新增按钮」,编辑弹窗出现,新增按钮消失,因此在 JSX 中,我们可以这样去表达他们的交互关系


{show ? (
  <div className="dialog">
    <input
      onChange={event => setDesc(event.target.value)}
      ref={inputRef}
      placeholder="请输入任务描述"
      onBlur={() => { setTimeout(() => { setShow(false) }, 0) }}
    />
    <div className="create" onClick={add}>创建</div>
  </div>
) : <div className="add" onClick={() => setShow(true)}>新增</div>}


input 框在失去焦点后编辑弹窗消失


我们可以使用 useRef  获得 input 组件的引用,以实现弹窗出现之后 input 能自动获取焦点的效果


const inputRef = useRef<HTMLInputElement>(null)


但是需要注意的是,input 元素是在 show 变成 true ,并且组件真实 DOM 再次渲染完成之后才能获取引用,因此这里运用了一个之后会学习的知识来解决这个问题


useEffect(() => {
// show 变成 true,并且组件渲染完成之后执行
  if (show) {
    inputRef.current?.focus()
  }
}, [show])


当编辑弹窗出现,我们在弹窗中输入内容,需要将输入内容保存在 desc 字段中。


基于只操作数据的思想,点击新增,其实只是往任务列表数据 jobs 中新增一个值


function add() {
  jobs.push({
    id: randomId(),
    desc,
    isSelected: false,
    createTime: Date.now()
  })
  setJobs([...jobs])
  setDesc('')
}


这里需要注意为了让 React 感知到你的数组发生了变化,需要重新创建一个新的引用数组。否则 React 无法识别。


jobs 表示任务列表,可以根据该数据遍历出整个列表


{jobs.map((job, i) => (
  <div className="job-wrapper" key={job.id}>
    <div className="selected" onClick={() => troggleSelected(i)}>
      {job.isSelected && <div className="circle"></div>}
    </div>
    <div className="desc">{job.desc}</div>
    <div className="remove" onClick={() => remove(i)}>删除</div>
  </div>
))}


删除与编辑都只需要修改对应的数组数据即可


function remove(i: number) {
  jobs.splice(i, 1)
  setJobs([...jobs])
}
function troggleSelected(i: number) {
  jobs[i].isSelected = !jobs[i].isSelected
  setJobs([...jobs])
}


就这样,我们轻松实现了一个列表的增删改查,完整代码如下


import { useEffect, useRef, useState } from 'react';
import { randomId } from './utils/index'
import logo from './logo.svg';
import './App.css';
interface Job {
  desc: string,
  id: string,
  createTime: number,
  isSelected: boolean
}
function App() {
  const [jobs, setJobs] = useState<Array<Job>>([])
  const [show, setShow] = useState(false)
  const [desc, setDesc] = useState('')
  const inputRef = useRef<HTMLInputElement>(null)
  useEffect(() => {
    if (show) {
      inputRef.current?.focus()
    }
  }, [show])
  function add() {
    jobs.push({
      id: randomId(),
      desc,
      isSelected: false,
      createTime: Date.now()
    })
    setJobs([...jobs])
    setDesc('')
  }
  function remove(i: number) {
    jobs.splice(i, 1)
    setJobs([...jobs])
  }
  function troggleSelected(i: number) {
    jobs[i].isSelected = !jobs[i].isSelected
    setJobs([...jobs])
  }
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>React 知命境</h1>
      </header>
      <div className="container">
        <div className="task-header">
          <div className="title">进行中的任务</div>
          <div className="right">...</div>
        </div>
        {jobs.map((job, i) => (
          <div className="job-wrapper" key={job.id}>
            <div className="selected" onClick={() => troggleSelected(i)}>
              {job.isSelected && <div className="circle"></div>}
            </div>
            <div className="desc">{job.desc}</div>
            <div className="remove" onClick={() => remove(i)}>删除</div>
          </div>
        ))}
        {show ? (
          <div className="dialog">
            <input
              onChange={event => setDesc(event.target.value)}
              ref={inputRef}
              placeholder="请输入任务描述"
              onBlur={() => { setTimeout(() => { setShow(false) }, 0) }}
            />
            <div className="create" onClick={add}>创建</div>
          </div>
        ) : <div className="add" onClick={() => setShow(true)}>新增</div>}
      </div>
    </div>
  );
}
export default App;


微信图片_20220511163430.png

很显然,代码功能虽然实现了,但是代码上并不简洁,学习了 React 哲学的同学可以思考一下,我们应该从哪些角度去思考如何进一步简化代码呢?

相关文章
|
4天前
|
存储 缓存 监控
71.7万/秒到1.4万/秒!数据库查询优化实战
在现代计算机系统中,程序的局部性原理是优化性能的关键。通过利用时间局部性和空间局部性,可以显著提升数据访问效率,减少高开销的操作如内存访问和网络 I/O。本文将探讨如何利用空间局部性原理,在实际案例中减少数据库查询量,并通过详细的监控和优化措施确保系统的稳定性和高效性。
71.7万/秒到1.4万/秒!数据库查询优化实战
|
25天前
|
SQL 关系型数据库 API
HarmonyOs开发:关系型数据库封装之增删改查
每个方法都预留了多种调用方式,比如使用callback异步回调或者使用Promise异步回调,亦或者同步执行,大家在使用的过程中,可以根据自身业务需要进行选择性调用,也分别暴露了成功和失败的方法,可以针对性的判断在执行的过程中是否执行成功。
88 13
|
2月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
234 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
2月前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
63 4
|
3月前
|
SQL NoSQL 数据库
Cassandra数据库与Cql实战笔记
Cassandra数据库与Cql实战笔记
63 1
Cassandra数据库与Cql实战笔记
|
2月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
488 1
|
3月前
|
前端开发 Java 数据库连接
javamvc配置,增删改查,文件上传下载。
【10月更文挑战第4天】javamvc配置,增删改查,文件上传下载。
45 1
|
2月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
252 0
|
3月前
|
JavaScript 前端开发 测试技术
[新手入门]todolist增删改查:vue3+ts版本!
【10月更文挑战第15天】[新手入门]todolist增删改查:vue3+ts版本!
|
20小时前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决