{"content":{"title":"【Sui】前端共学React学习笔记（3）","body":"![88f9d4b7250a724489ed6e23ff6ea7f.jpg](https://img.learnblockchain.cn/attachments/2025/01/zDGMnQL26788ea1ea25b3.jpg)\r\n请关注 **sui** 前端共学营及其社区，在这里你可以学到前端和 **move** 合约语言的知识。-\r\n## useReducer\r\n这里先给出一个简单的对`count`进行加减的功能\r\n```js\r\nimport { useState } from'react';\r\nfunction App() {\r\n  const [count, setCount] = useState(0);\r\n  const handleIncrement = () => { setCount(count + 1); };\r\n  const handleDecrement = () => { setCount(count - 1); };\r\n  return (\r\n    <div>\r\n      <button onClick={handleDecrement}>-</button>\r\n      <span>{count}</span>\r\n      <button onClick={handleIncrement}>+</button>\r\n    </div>\r\n  );\r\n}\r\nexport default App;\r\n```\r\n我们可以看到这里的功能非常单一，只有加和减，如果我们希望对数据的更改方式可能是更加多样的，比如乘和除的话就不方便对数据做统一的管理。现在我们可以使用`reduce`r使你的代码规范整洁。\r\n定义一个函数``countReducer``它接受state和action两个参数。`state`表示当前`reducer`函数要管理的那个状态，第二个`action`表示你要对状态进行什么样的操作。下面通过`switch`来判断`action`的属性`type`来进行相应操作，除了原先的操作还可以使用其他方式比如我这里地抛出异常。\r\n实际使用它就能把`useState`删除了换成`useReducer`，这边有两参数。第一个就是刚刚设置的`reducer`函数`countReducer`，第二个代表默认值这里设为0。`useReducer`的返回值与`useState`较为相似返回一个数组，第一个元素是他的当前状态值`state`，第二个是进行状态修改的触发器dispatch。\r\n接下来就可以直接触发器`dispatch`来进行相关操作后面带上参数`type`。\r\n```js\r\nimport { useReducer, useState } from'react';\r\n\r\nfunction countReducer(state, action) {\r\n  switch (action.type) {\r\n    case 'increment':\r\n      return state + 1;\r\n    case 'decrement':\r\n      return state - 1;\r\n    default:\r\n      throw new Error()\r\n  }\r\n}\r\n\r\nfunction App() {\r\n  const [state, dispatch] = useReducer(countReducer, 0)\r\n  const handleIncrement = () => dispatch({ type: 'increment' });\r\n  const handleDecrement = () => dispatch({ type: 'decrement' });\r\n  return (\r\n    <div>\r\n      <button onClick={handleDecrement}>-</button>\r\n      <span>{state}</span>\r\n      <button onClick={handleIncrement}>+</button>\r\n    </div>\r\n  );\r\n}\r\nexport default App;\r\n```\r\n## useRef\r\n现在我们有一个计数器点击加号就会加一，如果我们要记忆上个数值的话就可以使用`useRef`来进行创建数据存储的容器。\r\n这个上一次的值`prevCount`有几个特点，它的值可以手动修改但并不是一个相应是状态并且不会随着组件的更新而进行重新的更新。\r\n还有它的值进行设定是并不是给值本身做设置，而是通过调用`useRef`返回一个包含`current`属性的对象，所以操作是给`current`来做一个值的设定。\r\n```js\r\nfunction App() {\r\n  const [count, setCount] = useState(0);\r\n  const prevCount = useRef(count);\r\n  \r\n  function handleClick() {\r\n    prevCount.current = count;\r\n    setCount(count + 1);\r\n  }\r\n\r\n  return (\r\n    <div>\r\n      <p>最新count：{count}</p>\r\n      <p>上一次count：{prevCount.current}</p>\r\n      <button onClick={handleClick}>+</button>\r\n    </div>\r\n  );\r\n}\r\n```\r\n我们在使用`useRef`除了可以引用之前的状态值外话可以来引用页面中的标签。\r\n子默认不对外开放内部功能，如果我们希望设置一个方法能被父组件使用的话，就需要一下特殊处理，首先子组件不能直接定义为一个普通函数，而是要通过`const`的函数表达方式来做定义，并且要通过React的方法`forwardRef`来处理这样才可以被父组件使用，这时我们的子组件还需要接受我们外部的`ref`。\r\n```js\r\nconst Child = forwardRef(function(props， ref) {\r\n  return (\r\n    <div>子组件</div>\r\n  )\r\n})\r\n\r\nfunction App() {\r\n  const childrRef = useRef(); \r\n  function handleClick() {\r\n    \r\n  }\r\n\r\n  return (\r\n    <div>\r\n      <Child ref={childrRef}/>\r\n      <button onClick={handleClick}>按钮</button>\r\n    </div>\r\n  );\r\n}\r\n```"},"author":{"user":"https://learnblockchain.cn/people/23988","address":null},"history":"bafkreib2lt7yzbern3537ia72c44tbdgeal4ut4ffjsks2fknosk76bgpi","timestamp":1737129968,"version":1}