当前位置: 首页 > news >正文

第3课:状态管理与事件处理

第3课:状态管理与事件处理

学习目标

  • 掌握useState Hook的使用
  • 理解组件事件处理机制
  • 实现表单输入与状态绑定
  • 完成任务添加功能原型

一、useState基础

1. 创建第一个状态

新建src/Counter.js

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>当前计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <button onClick={() => setCount(count - 1)}>减少</button>
    </div>
  );
}

export default Counter;
import { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me+1</button>
        <button onClick={() => setCount(count - 1)}>Click me-1</button>
    </div>
  );
}
export default Counter;
// // import React from 'react'

关键点解析:

  • useState返回当前状态和更新函数
  • 状态更新会触发组件重新渲染
  • 永远不要直接修改状态,必须使用状态更新函数

2. 在App组件中使用

import Counter from './Counter';

function App() {
  return (
    <div className="App">
      <Counter />
    </div>
  );
}
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import HelloWorld from './HelloWorld.jsx'
import Introduction from './Introduction.jsx'
import JsxDemo from './JsxDemo.jsx'
import Greeting from './Greeting.jsx'
import InlineStyleDemo from './InlineStyleDemo.jsx'
import Card from './Card.jsx';
import TaskCard from './TaskCard.jsx'
import Counter from './Counter.jsx'

function App() {
  
  return (
    <>
      <div className='App'>
        <Counter />

      </div>
    </>
  )
}

export default App

在这里插入图片描述

二、表单处理基础

1. 受控组件实现

新建src/InputDemo.js

import { useState } from 'react';

function InputDemo() {
  const [inputValue, setInputValue] = useState('');
  const [displayText, setDisplayText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    setDisplayText(inputValue);
    setInputValue('');
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="输入内容..."
        />
        <button type="submit">提交</button>
      </form>
      {displayText && <p>你输入的内容是:{displayText}</p>}
    </div>
  );
}

export default InputDemo;
import { useState } from "react";
function InputDemo() {
  const [inputValue, setInputValue] = useState("");
  const [displayValue, setDisplayValue] = useState("");

  const handleChange = (event) => {
    event.preventDefault();
    setDisplayValue(inputValue);
    setInputValue('');
  };

  return (
    <div>
      <h1>Input Demo</h1>
      <form onSubmit={handleChange}>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="Type something..."
        />
        <button type="submit">Submit</button>
      </form>
        <p>You typed: {displayValue}</p>
    </div>
  );
}
export default InputDemo;
// // // import React from 'react'
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import HelloWorld from './HelloWorld.jsx'
import Introduction from './Introduction.jsx'
import JsxDemo from './JsxDemo.jsx'
import Greeting from './Greeting.jsx'
import InlineStyleDemo from './InlineStyleDemo.jsx'
import Card from './Card.jsx';
import TaskCard from './TaskCard.jsx'
import Counter from './Counter.jsx'
import InputDemo from './InputDemo.jsx'

function App() {
  
  return (
    <>
      <div className='App'>
        <InputDemo />
      </div>
    </>
  )
}

export default App

在这里插入图片描述

2. 多字段表单处理

function UserForm() {
  const [formData, setFormData] = useState({
    username: '',
    email: '',
    password: ''
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('表单数据:', formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        name="username"
        value={formData.username}
        onChange={handleChange}
        placeholder="用户名"
      />
      <input
        name="email"
        type="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="邮箱"
      />
      <input
        name="password"
        type="password"
        value={formData.password}
        onChange={handleChange}
        placeholder="密码"
      />
      <button type="submit">注册</button>
    </form>
  );
}
import { useState } from "react";
function UserForm() {
    const [formData, setFormData] = useState({
        name: "",
        email: "",
        password: "",
        confirmPassword: "",
      });
      
      const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData((prevData) => ({
          ...prevData,
          [name]: value,
        }));
      };
      
      const handleSubmit = (e) => {
        e.preventDefault();
        console.log('The form data:',formData);
        // Perform form validation here
        // If validation passes, submit the form data
        // If validation fails, display error messages
      };
      
      return (
        <>
          <form onSubmit={handleSubmit}>
              <input name="username" 
              value={formData.username}
              onChange={handleChange}
              placeholder="Username"/>
              <input name="email"
              type="email"
              value={formData.email}
              onChange={handleChange}
              placeholder="Email"/>
              <input name="password"
              type="password"
              value={formData.password}
              onChange={handleChange}
              placeholder="Password"/>
              <input name="confirmPassword"
              type="password"
              value={formData.confirmPassword}
              onChange={handleChange}
              placeholder="Confirm Password"/>
              <button type="submit">Submit</button>
              
      
          </form>
          <p>Username: {formData.username}</p>
          </>
      );
}

export default UserForm;
// // // import React from 'react'

```bash
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import HelloWorld from './HelloWorld.jsx'
import Introduction from './Introduction.jsx'
import JsxDemo from './JsxDemo.jsx'
import Greeting from './Greeting.jsx'
import InlineStyleDemo from './InlineStyleDemo.jsx'
import Card from './Card.jsx';
import TaskCard from './TaskCard.jsx'
import Counter from './Counter.jsx'
import InputDemo from './InputDemo.jsx'
import UserForm from './UserForm.jsx'

function App() {
  
  return (
    <>
      <div className='App'>
        <UserForm />
      </div>
    </>
  )
}

export default App

在这里插入图片描述

  • 以下未验证,明天验证:

三、任务管理系统集成

1. 状态提升到App组件

修改App.js

import { useState } from 'react';
import TaskCard from './TaskCard';

function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: '学习React基础', completed: false },
    { id: 2, text: '完成课后练习', completed: true }
  ]);

  return (
    <div className="App">
      <h1>任务管理系统</h1>
      <div className="task-list">
        {tasks.map(task => (
          <TaskCard
            key={task.id}
            title={task.text}
            completed={task.completed}
          />
        ))}
      </div>
    </div>
  );
}

2. 添加任务功能组件

新建src/AddTask.js

import { useState } from 'react';

function AddTask({ onAddTask }) {
  const [newTask, setNewTask] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!newTask.trim()) return;
    
    onAddTask({
      id: Date.now(),
      text: newTask,
      completed: false
    });
    setNewTask('');
  };

  return (
    <form onSubmit={handleSubmit} className="add-task-form">
      <input
        type="text"
        value={newTask}
        onChange={(e) => setNewTask(e.target.value)}
        placeholder="添加新任务..."
      />
      <button type="submit">添加</button>
    </form>
  );
}

export default AddTask;

3. 完整功能集成

更新App.js

function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: '学习React基础', completed: false },
    { id: 2, text: '完成课后练习', completed: true }
  ]);

  const addTask = (newTask) => {
    setTasks([...tasks, newTask]);
  };

  const toggleTask = (taskId) => {
    setTasks(tasks.map(task =>
      task.id === taskId 
        ? { ...task, completed: !task.completed } 
        : task
    ));
  };

  return (
    <div className="App">
      <h1>任务管理系统</h1>
      <AddTask onAddTask={addTask} />
      <div className="task-list">
        {tasks.map(task => (
          <TaskCard
            key={task.id}
            title={task.text}
            completed={task.completed}
            onToggle={() => toggleTask(task.id)}
          />
        ))}
      </div>
    </div>
  );
}

更新TaskCard.js

function TaskCard({ title, completed, onToggle }) {
  return (
    <div className={`task-card ${completed ? 'completed' : ''}`}>
      <h3>{title}</h3>
      <div className="task-actions">
        <button onClick={onToggle}>
          {completed ? '标记未完成' : '标记完成'}
        </button>
      </div>
    </div>
  );
}

四、样式优化

添加src/App.css

.App {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.add-task-form {
  margin-bottom: 20px;
  display: flex;
  gap: 10px;
}

.add-task-form input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.add-task-form button {
  padding: 8px 16px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.task-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.task-card {
  /* 原有样式基础上添加 */
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px;
}

.task-actions button {
  padding: 6px 12px;
  background-color: #2196F3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.task-card.completed {
  opacity: 0.7;
}

五、练习任务

  1. 实现删除任务功能:

    • 为每个任务卡片添加删除按钮
    • 创建deleteTask方法
    • 使用filter方法更新状态
  2. 为添加任务表单添加验证:

    • 输入不能为空
    • 输入长度不能超过50字符
    • 显示实时字符计数
  3. (挑战)添加任务分类功能:

    • 添加选择器选择任务类型(工作/学习/生活)
    • 在任务卡片显示对应类型图标

六、常见问题解答

Q: 为什么状态更新后界面没有变化?
A: 检查是否:

  1. 正确使用了状态更新函数
  2. 状态值确实是新的(对于对象/数组需要创建新引用)
  3. 组件是否正确接收了props

Q: 如何处理多个状态?
A: 可以:

  1. 使用多个useState
  2. 合并相关状态到一个对象
  3. 当状态相互关联时,优先考虑合并

Q: 为什么表单提交后页面刷新?
A: 确保:

  1. 表单提交处理函数中有e.preventDefault()
  2. 按钮类型不是submit(如果不需要表单提交)

七、课程总结

今天我们掌握了:

  • useState Hook的基本用法
  • 表单事件处理流程
  • 组件间的状态传递
  • 实现了一个交互式的任务管理系统原型

课后作业

  1. 完成删除功能实现
  2. 为任务添加优先级属性(高/中/低)
  3. 尝试使用本地存储保存任务数据(提前预习下节课内容)

下一节课我们将学习列表渲染与条件渲染的进阶技巧!

http://www.dtcms.com/a/113776.html

相关文章:

  • IntelliJ IDEA中Spring Boot 3.4.x+集成Redis 7.x:最新配置与实战指南
  • Drools项目实战
  • 第八课:在SD中安装拓展插件
  • 设计模式简述(四)模板方法模式
  • C#里使用libxl来改变字体的特性
  • AI Agent设计模式五:Orchestrator
  • form实现pdf文件转换成jpg文件
  • Spring Cloud 框架为什么能处理高并发
  • python基础-16-处理csv文件和json数据
  • 未来已来:探索AI驱动的HMI设计新方向
  • 动画过渡设置
  • 【JS】接雨水题解
  • 春季赛day15 Snailography
  • 铁电液晶(FLC)与反铁电液晶(AFLC)
  • SCADE One - 弥合基于模型设计与传统编程之间的鸿沟
  • 【学Rust写CAD】31 muldiv255函数(muldiv255.rs)
  • 设计模式简述(三)工厂模式
  • 《C语言代码解析与应用:数组操作的两种实现》
  • ctfshow VIP题目限免 版本控制泄露源码2
  • LeetCode详解之如何一步步优化到最佳解法:20. 有效的括号
  • 配置ASP.NET Core+NLog配置日志示例
  • 基于 FPGA 的分秒计数器
  • 如何实现两个视频融合EasyCVR平台的数据同步?详细步骤指南
  • 爬虫练习案例
  • zk基础—5.Curator的使用与剖析二
  • 打造高效英文单词记忆系统:基于Python的实现与分析
  • $R^n$超平面约束下的向量列
  • 游戏引擎学习第206天
  • React框架的Hooks实现原理
  • MicroPython 开发ESP32应用教程 之 WIFI简单应用 :时间同步、天气信息获取,ST7735 TFT屏驱动及任意中文字符显示