React交互学习篇

React添加交互篇


一、响应事件

在事件处理函数中读取 props

由于事件处理函数声明于组件内部,因此它们可以直接访问组件的 props。示例中的按钮,当点击时会弹出带有 message prop 的 alert:

javascript 复制代码
function AlertButton({ message, children }) {
  return (
    <button onClick={() => alert(message)}>
      {children}
    </button>
  );
}

export default function Toolbar() {
  return (
    <div>
      <AlertButton message="正在播放!">
        播放电影
      </AlertButton>
      <AlertButton message="正在上传!">
        上传图片
      </AlertButton>
    </div>
  );
}

将事件处理函数作为 props 传递

通常,我们会在父组件中定义子组件的事件处理函数。比如:置于不同位置的 Button 组件,可能最终执行的功能也不同 ------ 也许是播放电影,也许是上传图片。

为此,将组件从父组件接收的 prop 作为事件处理函数传递,如下所示:

javascript 复制代码
function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

function PlayButton({ movieName }) {
  function handlePlayClick() {
    alert(`正在播放 ${movieName}!`);
  }

  return (
    <Button onClick={handlePlayClick}>
      播放 "{movieName}"
    </Button>
  );
}

function UploadButton() {
  return (
    <Button onClick={() => alert('正在上传!')}>
      上传图片
    </Button>
  );
}

export default function Toolbar() {
  return (
    <div>
      <PlayButton movieName="魔女宅急便" />
      <UploadButton />
    </div>
  );
}

示例中,Toolbar 组件渲染了一个 PlayButton 组件和 UploadButton 组件:

  • PlayButtonhandlePlayClick 作为 onClick prop 传入 Button 组件内部。
  • UploadButton() => alert('正在上传!') 作为 onClick prop 传入 Button 组件内部。

最后,你的 Button 组件接收一个名为 onClick 的 prop。它直接将这个 prop 以 onClick={onClick} 方式传递给浏览器内置的 <button>。当点击按钮时,React 会调用传入的函数。

命名事件处理函数 prop

内置组件(<button><div>)仅支持 浏览器事件名称,例如 onClick。但是,当你构建自己的组件时,你可以按你个人喜好命名事件处理函数的 prop。

按照惯例,事件处理函数 props 应该以 on 开头,后跟一个大写字母。

javascript 复制代码
export default function App() {
  return (
    <Toolbar
      onPlayMovie={() => alert('正在播放!')}
      onUploadImage={() => alert('正在上传!')}
    />
  );
}

function Toolbar({ onPlayMovie, onUploadImage }) {
  return (
    <div>
      <Button onClick={onPlayMovie}>
        播放电影
      </Button>
      <Button onClick={onUploadImage}>
        上传图片
      </Button>
    </div>
  );
}

function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

二、state:组件的记忆

添加一个state变量

javascript 复制代码
import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

剖析 useState

当你调用 useState 时,你是在告诉 React 你想让这个组件记住一些东西:

scss 复制代码
const [index, setIndex] = useState(0);

在这个例子里,你希望 React 记住 index

惯例是将这对返回值命名为 const [thing, setThing]。你也可以将其命名为任何你喜欢的名称,但遵照约定俗成能使跨项目合作更易理解。

useState 的唯一参数是 state 变量的初始值 。在这个例子中,index 的初始值被useState(0)设置为 0

每次你的组件渲染时,useState 都会给你一个包含两个值的数组:

  1. state 变量 (index) 会保存上次渲染的值。
  2. state setter 函数 (setIndex) 可以更新 state 变量并触发 React 重新渲染组件。

以下是实际发生的情况:

scss 复制代码
const [index, setIndex] = useState(0);
  1. 组件进行第一次渲染。 因为你将 0 作为 index 的初始值传递给 useState,它将返回 [0, setIndex]。 React 记住 0 是最新的 state 值。
  2. 你更新了 state 。当用户点击按钮时,它会调用 setIndex(index + 1)index0,所以它是 setIndex(1)。这告诉 React 现在记住 index1 并触发下一次渲染。
  3. 组件进行第二次渲染 。React 仍然看到 useState(0),但是因为 React 记住 了你将 index 设置为了 1,它将返回 [1, setIndex]
  4. 以此类推!

赋予一个组件多个 state 变量

你可以在一个组件中拥有任意多种类型的 state 变量。该组件有两个 state 变量,一个数字 index 和一个布尔值 showMore,点击 "Show Details" 会改变 showMore 的值:

javascript 复制代码
import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  function handleNextClick() {
    setIndex(index + 1);
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
    </>
  );
}

State 是隔离且私有的

State 是屏幕上组件实例内部的状态。换句话说,如果你渲染同一个组件两次,每个副本都会有完全隔离的 state!改变其中一个不会影响另一个。

相关推荐
KKKK1 小时前
一次React19.2 Activity 组件使用问题排查
react.js
wordbaby2 小时前
React 误区粉碎:useEffectEvent 是“非响应式”的,所以它不会触发重渲染?
前端·react.js
crary,记忆3 小时前
React 之 useEffect
前端·javascript·学习·react.js
锈儿海老师5 小时前
深入探究 React 史上最大安全漏洞
前端·react.js·next.js
xiechao6 小时前
函数组件 useEffect 清理函数抛错:ErrorBoundary 能捕获吗?
前端·react.js
wordbaby6 小时前
组件与外部世界的桥梁:一文读懂 useEffect 的核心机制
前端·react.js
wordbaby6 小时前
永远不要欺骗 React:详解 useEffect 依赖规则与“闭包陷阱”
前端·react.js
暮之沧蓝8 小时前
React(18-19)总结
前端·react.js·前端框架
一直在学习的小白~8 小时前
React大模型网站-流式推送markdown转换问题以及开启 rehype-raw,rehype-sanitize,remark-gfm等插件的使用
react.js·chatgpt·文心一言