From 7d0945a5459dc2292a20bd674a7a4cc402b7b836 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Tue, 5 Mar 2024 10:24:14 +0800
Subject: [PATCH 01/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/react-lifecycles-compat.md | 130 ++++++++++++++++++++++++++++++++
1 file changed, 130 insertions(+)
create mode 100644 1224/react-lifecycles-compat.md
diff --git a/1224/react-lifecycles-compat.md b/1224/react-lifecycles-compat.md
new file mode 100644
index 00000000..34a25e4a
--- /dev/null
+++ b/1224/react-lifecycles-compat.md
@@ -0,0 +1,130 @@
+> 模板版本:v0.1.3
+
+
+
react-lifecycles-compat
+
+
+
+
+
+
+
+
+> [!TIP] [Github 地址](https://github.com/reactjs/react-lifecycles-compat)
+
+## 安装与使用
+
+进入到工程目录并输入以下命令:
+
+>[!TIP] # 处替换为 tgz 包的路径
+
+
+
+#### **npm**
+
+```bash
+npm install react-lifecycles-compat@3.0.4
+```
+
+#### **yarn**
+
+```bash
+yarn add react-lifecycles-compat@file@3.0.4
+```
+
+
+
+下面的代码展示了这个库的基本使用场景:
+
+```js
+import React from 'react';
+import {
+ Text,
+ View,
+ Button
+} from 'react-native';
+import { polyfill } from 'react-lifecycles-compat';
+import { State } from 'react-native-gesture-handler';
+class ShowComponent extends React.Component {
+ render() {
+ return (
+
+ 新组件
+
+ )
+ }
+}
+class ExampleComponent extends React.Component {
+ state = {
+ Text1: '未执行',
+ count1: 0,
+ Text2: '未执行',
+ visible: false
+ };
+ static getDerivedStateFromProps = (nextProps, prevState) => {
+ // Normally this method would only work for React 16.3 and newer,
+ // But the polyfill will make it work for older versions also!
+ return { Text1: '已执行', count1: prevState.count1 + 1 }
+ }
+
+ getSnapshotBeforeUpdate(prevProps, prevState) {
+ // Normally this method would only work for React 16.3 and newer,
+ // But the polyfill will make it work for older versions also!
+ return true
+ }
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ if (snapshot) {
+ if (this.state.Text2 !== '已执行') {
+ this.setState({
+ Text2: '已执行'
+ })
+ }
+
+ }
+ }
+ // render() and other methods ...
+ handleClick = () => {
+ this.setState({ visible: true })
+ }
+ render() {
+ const { visible, Text1, Text2, count1 } = this.state
+ return (
+
+ {visible ? : {visible}}
+ getDerivedStateFromProps生命周期会在React初始化挂载和后续更新时调用render之前调用,返回一个对象来更新state,或者返回null就不更新任何内容
+ getSnapshotBeforeUpdate生命周期会在React更新DOM之前时直接调用,使你的组件能够在DOM发生更改之前捕获一些信息
+
+ 生命周期getDerivedStateFromProps{this.state.Text1}+{this.state.count1}
+ 生命周期getSnapshotBeforeUpdate{this.state.Text2}
+
+ )
+ }
+
+}
+
+// Polyfill your component so the new lifecycles will work with older versions of React:
+polyfill(ExampleComponent);
+
+export default ExampleComponent;
+```
+
+### 兼容性
+
+在以下版本验证通过
+
+1. RNOH:0.72.13; SDK:HarmonyOS NEXT Developer Preview1; IDE:DevEco Studio 4.1.3.500; ROM:204.1.0.59;
+
+| Name | Description | Required | Platform | HarmonyOS Support |
+| ------------------------ | -------------------------------------- | -------- | -------- | ----------------- |
+| getDerivedStateFromProps | Initialize the mount. | NO | Android | YES |
+| getSnapshotBeforeUpdate | Call directly before updating the DOM. | NO | Android | YES |
+
+## 遗留问题
+
+## 其他
+
+Note that in order for the polyfill to work, none of the following lifecycles can be defined by your component: `componentWillMount`, `componentWillReceiveProps`, or `componentWillUpdate`.
+
+Note also that if your component contains `getSnapshotBeforeUpdate`, `componentDidUpdate` must be defined as well.
+
+An error will be thrown if any of the above conditions are not met.
--
Gitee
From ac0c8be2fd56446c120e2aaf339af3cb7d908942 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Tue, 5 Mar 2024 10:48:21 +0800
Subject: [PATCH 02/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/react-lifecycles-compat.md | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/1224/react-lifecycles-compat.md b/1224/react-lifecycles-compat.md
index 34a25e4a..513148ff 100644
--- a/1224/react-lifecycles-compat.md
+++ b/1224/react-lifecycles-compat.md
@@ -29,7 +29,7 @@ npm install react-lifecycles-compat@3.0.4
#### **yarn**
```bash
-yarn add react-lifecycles-compat@file@3.0.4
+yarn add react-lifecycles-compat@3.0.4
```
@@ -123,8 +123,6 @@ export default ExampleComponent;
## 其他
-Note that in order for the polyfill to work, none of the following lifecycles can be defined by your component: `componentWillMount`, `componentWillReceiveProps`, or `componentWillUpdate`.
+请注意,为了使polyfill工作,您的组件不能定义以下生命周期:componentWillMount,componentWillReceiveProps,componentWillUpdate.
-Note also that if your component contains `getSnapshotBeforeUpdate`, `componentDidUpdate` must be defined as well.
-
-An error will be thrown if any of the above conditions are not met.
+还要注意,如果您的组件包含getSnapshotBeforeUpdate,那么也必须定义componentDidUpdate,如果不满足上述任何条件,将抛出错误.
--
Gitee
From 52fc80cc5db63a68f4fda8e622d4766f227d03d1 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Tue, 5 Mar 2024 11:14:50 +0800
Subject: [PATCH 03/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/react-lifecycles-compat.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/1224/react-lifecycles-compat.md b/1224/react-lifecycles-compat.md
index 513148ff..aefa952d 100644
--- a/1224/react-lifecycles-compat.md
+++ b/1224/react-lifecycles-compat.md
@@ -123,6 +123,8 @@ export default ExampleComponent;
## 其他
-请注意,为了使polyfill工作,您的组件不能定义以下生命周期:componentWillMount,componentWillReceiveProps,componentWillUpdate.
+以下事项于原库保持一致需注意遵循:
-还要注意,如果您的组件包含getSnapshotBeforeUpdate,那么也必须定义componentDidUpdate,如果不满足上述任何条件,将抛出错误.
+为了使polyfill工作,您的组件不能定义以下生命周期:componentWillMount,componentWillReceiveProps,componentWillUpdate.
+
+如果您的组件包含getSnapshotBeforeUpdate,那么也必须定义componentDidUpdate,如果不满足上述任何条件,将抛出错误.
--
Gitee
From bccb00343ec1bb0598228700a982847b5820d79e Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Tue, 5 Mar 2024 11:25:12 +0800
Subject: [PATCH 04/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/react-lifecycles-compat.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/1224/react-lifecycles-compat.md b/1224/react-lifecycles-compat.md
index aefa952d..0ee89e30 100644
--- a/1224/react-lifecycles-compat.md
+++ b/1224/react-lifecycles-compat.md
@@ -123,7 +123,7 @@ export default ExampleComponent;
## 其他
-以下事项于原库保持一致需注意遵循:
+以下事项与原库保持一致需注意遵循:
为了使polyfill工作,您的组件不能定义以下生命周期:componentWillMount,componentWillReceiveProps,componentWillUpdate.
--
Gitee
From 54cbbaac782d3924d57782e3461e7c07490006b3 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Wed, 6 Mar 2024 11:56:24 +0800
Subject: [PATCH 05/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/axios.md | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
create mode 100644 1224/axios.md
diff --git a/1224/axios.md b/1224/axios.md
new file mode 100644
index 00000000..8dadf1ae
--- /dev/null
+++ b/1224/axios.md
@@ -0,0 +1,149 @@
+> 模板版本:v0.1.3
+
+
+
axios
+
+
+
+
+
+
+> [!tip] [Github 地址](https://github.com/axios/axios)
+
+## 安装与使用
+
+#### **npm**
+
+```bash
+npm install axios@0.28.0
+```
+
+#### **bower**
+
+```bash
+bower install axios@0.28.0
+```
+
+#### **yarn**
+
+```bash
+yarn add axios@0.28.0
+```
+
+Once the package is installed, you can import the library using `import` or `require` approach:
+
+```js
+import axios, {isCancel, AxiosError} from 'axios';
+```
+
+You can also use the default export, since the named export is just a re-export from the Axios factory:
+
+```js
+import axios from 'axios';
+
+console.log(axios.isCancel('something'));
+```
+
+
+下面的代码展示了这个库的基本使用场景:
+
+>[!WARNING] 使用时 import 的库名不变。
+
+```js
+import axios from 'axios';
+//const axios = require('axios'); // legacy way
+
+// Make a request for a user with a given ID
+axios.get('/user?ID=12345')
+ .then(function (response) {
+ // handle success
+ console.log(response);
+ })
+ .catch(function (error) {
+ // handle error
+ console.log(error);
+ })
+ .finally(function () {
+ // always executed
+ });
+
+// Optionally the request above could also be done as
+axios.get('/user', {
+ params: {
+ ID: 12345
+ }
+ })
+ .then(function (response) {
+ console.log(response);
+ })
+ .catch(function (error) {
+ console.log(error);
+ })
+ .finally(function () {
+ // always executed
+ });
+
+// Want to use async/await? Add the `async` keyword to your outer function/method.
+async function getUser() {
+ try {
+ const response = await axios.get('/user?ID=12345');
+ console.log(response);
+ } catch (error) {
+ console.error(error);
+ }
+}
+```
+
+## 约束与限制
+
+## 兼容性
+
+本文档内容基于以下版本验证通过:
+
+1. RNOH:0.72.13; SDK:HarmonyOS NEXT Developer Preview1; IDE:DevEco Studio 4.1.3.500; ROM:2.0.0.59;
+
+## API
+
+> [!tip] "Platform"列表示该属性在原三方库上支持的平台。
+
+> [!tip] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
+
+| Name | Description | Type | Required | HarmonyOS Support |
+| :------------ | ----------- | :--: | :------: | :----------------: |
+| axios.request(config) | 别名发送request请求 | function | / | yes |
+| axios.get(url[, config]) | 别名发送get请求 | function | / | yes |
+| axios.delete(url[, config]) | 别名发送delete请求 | function | / | yes |
+| axios.head(url[, config]) | 别名发送head请求 | function | / | yes |
+| axios.options(url[, config]) | 别名发送options请求 | function | / | yes |
+| axios.post(url[, data[, config]]) | 别名发送post请求 | function | / | yes |
+| axios.put(url[, data[, config]]) | 别名发送put请求 | function | / | yes |
+| axios.patch(url[, data[, config]]) | 别名发送patch请求 | function | / | yes |
+| axios#request(config) | 实例发送request请求 | function | / | yes |
+| axios#get(url[, config]) | 实例发送get请求 | function | / | yes |
+| axios#delete(url[, config]) | 实例发送delete请求 | function | / | yes |
+| axios#head(url[, config]) | 实例发送head请求 | function | / | yes |
+| axios#options(url[, config]) | 实例发送options请求 | function | / | yes |
+| axios#post(url[, data[, config]]) | 实例发送post请求 | function | / | yes |
+| axios#put(url[, data[, config]]) | 实例发送put请求 | function | / | yes |
+| axios#patch(url[, data[, config]]) | 实例发送patch请求 | function | / | yes |
+| url | 配置中请求的地址 | function | / | yes |
+| method | 配置中请求时使用的方法 | function | / | yes |
+| baseURL | 配置中自动加在url地址前 | function | / | yes |
+| headers | 配置中自定义请求头 | function | / | yes |
+| params | 配置中请求一起发送时的参数 | function | / | yes |
+| data | 配置中请求体发送的数据 | function | / | yes |
+| timeout | 配置中请求超时的毫秒数 | function | / | yes |
+| proxy | 配置中设置代理 | function | / | yes |
+| Response Schema | 响应类型 | function | / | yes |
+| Config Defaults | 默认配置 | function | / | yes |
+| requestInterceptors | 请求拦截器 | function | / | yes |
+| responseInterceptors | 响应拦截器 | function | / | yes |
+| Handling Errors | 错误处理 | function | / | yes |
+| AbortController | 中止控制器 | function | / | yes |
+| CancelToken | 取消令牌 | function | / | yes |
+
+## 其他
+
+## 开源协议
+
+本项目基于 [The MIT License (MIT)](https://github.com/Kureev/react-native-blur/blob/master/LICENSE) ,请自由地享受和参与开源。
--
Gitee
From cdb0bc4ad97c967bc7f90fa574d69a88b495b840 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Wed, 6 Mar 2024 12:00:37 +0800
Subject: [PATCH 06/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/axios.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/1224/axios.md b/1224/axios.md
index 8dadf1ae..0e765853 100644
--- a/1224/axios.md
+++ b/1224/axios.md
@@ -8,7 +8,7 @@
-> [!tip] [Github 地址](https://github.com/axios/axios)
+> [!TIP] [Github 地址](https://github.com/axios/axios)
## 安装与使用
--
Gitee
From 1dd30421e09dcd6a5df46742d9bf5f607ea605c1 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Wed, 6 Mar 2024 12:04:53 +0800
Subject: [PATCH 07/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/axios.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/1224/axios.md b/1224/axios.md
index 0e765853..fae2d4d8 100644
--- a/1224/axios.md
+++ b/1224/axios.md
@@ -8,6 +8,8 @@
+
+
> [!TIP] [Github 地址](https://github.com/axios/axios)
## 安装与使用
--
Gitee
From cab45f720141b222a309a98e5069915da9acf855 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Wed, 6 Mar 2024 12:05:25 +0800
Subject: [PATCH 08/10] =?UTF-8?q?[Issues:=20#I95SUW]=20=E6=B7=BB=E5=8A=A0r?=
=?UTF-8?q?eact-lifecycles-compat=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/axios.md | 151 --------------------------------------------------
1 file changed, 151 deletions(-)
delete mode 100644 1224/axios.md
diff --git a/1224/axios.md b/1224/axios.md
deleted file mode 100644
index fae2d4d8..00000000
--- a/1224/axios.md
+++ /dev/null
@@ -1,151 +0,0 @@
-> 模板版本:v0.1.3
-
-
-
axios
-
-
-
-
-
-
-
-
-> [!TIP] [Github 地址](https://github.com/axios/axios)
-
-## 安装与使用
-
-#### **npm**
-
-```bash
-npm install axios@0.28.0
-```
-
-#### **bower**
-
-```bash
-bower install axios@0.28.0
-```
-
-#### **yarn**
-
-```bash
-yarn add axios@0.28.0
-```
-
-Once the package is installed, you can import the library using `import` or `require` approach:
-
-```js
-import axios, {isCancel, AxiosError} from 'axios';
-```
-
-You can also use the default export, since the named export is just a re-export from the Axios factory:
-
-```js
-import axios from 'axios';
-
-console.log(axios.isCancel('something'));
-```
-
-
-下面的代码展示了这个库的基本使用场景:
-
->[!WARNING] 使用时 import 的库名不变。
-
-```js
-import axios from 'axios';
-//const axios = require('axios'); // legacy way
-
-// Make a request for a user with a given ID
-axios.get('/user?ID=12345')
- .then(function (response) {
- // handle success
- console.log(response);
- })
- .catch(function (error) {
- // handle error
- console.log(error);
- })
- .finally(function () {
- // always executed
- });
-
-// Optionally the request above could also be done as
-axios.get('/user', {
- params: {
- ID: 12345
- }
- })
- .then(function (response) {
- console.log(response);
- })
- .catch(function (error) {
- console.log(error);
- })
- .finally(function () {
- // always executed
- });
-
-// Want to use async/await? Add the `async` keyword to your outer function/method.
-async function getUser() {
- try {
- const response = await axios.get('/user?ID=12345');
- console.log(response);
- } catch (error) {
- console.error(error);
- }
-}
-```
-
-## 约束与限制
-
-## 兼容性
-
-本文档内容基于以下版本验证通过:
-
-1. RNOH:0.72.13; SDK:HarmonyOS NEXT Developer Preview1; IDE:DevEco Studio 4.1.3.500; ROM:2.0.0.59;
-
-## API
-
-> [!tip] "Platform"列表示该属性在原三方库上支持的平台。
-
-> [!tip] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
-
-| Name | Description | Type | Required | HarmonyOS Support |
-| :------------ | ----------- | :--: | :------: | :----------------: |
-| axios.request(config) | 别名发送request请求 | function | / | yes |
-| axios.get(url[, config]) | 别名发送get请求 | function | / | yes |
-| axios.delete(url[, config]) | 别名发送delete请求 | function | / | yes |
-| axios.head(url[, config]) | 别名发送head请求 | function | / | yes |
-| axios.options(url[, config]) | 别名发送options请求 | function | / | yes |
-| axios.post(url[, data[, config]]) | 别名发送post请求 | function | / | yes |
-| axios.put(url[, data[, config]]) | 别名发送put请求 | function | / | yes |
-| axios.patch(url[, data[, config]]) | 别名发送patch请求 | function | / | yes |
-| axios#request(config) | 实例发送request请求 | function | / | yes |
-| axios#get(url[, config]) | 实例发送get请求 | function | / | yes |
-| axios#delete(url[, config]) | 实例发送delete请求 | function | / | yes |
-| axios#head(url[, config]) | 实例发送head请求 | function | / | yes |
-| axios#options(url[, config]) | 实例发送options请求 | function | / | yes |
-| axios#post(url[, data[, config]]) | 实例发送post请求 | function | / | yes |
-| axios#put(url[, data[, config]]) | 实例发送put请求 | function | / | yes |
-| axios#patch(url[, data[, config]]) | 实例发送patch请求 | function | / | yes |
-| url | 配置中请求的地址 | function | / | yes |
-| method | 配置中请求时使用的方法 | function | / | yes |
-| baseURL | 配置中自动加在url地址前 | function | / | yes |
-| headers | 配置中自定义请求头 | function | / | yes |
-| params | 配置中请求一起发送时的参数 | function | / | yes |
-| data | 配置中请求体发送的数据 | function | / | yes |
-| timeout | 配置中请求超时的毫秒数 | function | / | yes |
-| proxy | 配置中设置代理 | function | / | yes |
-| Response Schema | 响应类型 | function | / | yes |
-| Config Defaults | 默认配置 | function | / | yes |
-| requestInterceptors | 请求拦截器 | function | / | yes |
-| responseInterceptors | 响应拦截器 | function | / | yes |
-| Handling Errors | 错误处理 | function | / | yes |
-| AbortController | 中止控制器 | function | / | yes |
-| CancelToken | 取消令牌 | function | / | yes |
-
-## 其他
-
-## 开源协议
-
-本项目基于 [The MIT License (MIT)](https://github.com/Kureev/react-native-blur/blob/master/LICENSE) ,请自由地享受和参与开源。
--
Gitee
From d712b1c8556f7d159bb7bcc84d9cd1f061f20d55 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Wed, 20 Mar 2024 10:03:26 +0800
Subject: [PATCH 09/10] =?UTF-8?q?[Issues:=20#I99Y71]=20=E6=B7=BB=E5=8A=A0i?=
=?UTF-8?q?mmer=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/Immer.md | 736 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 736 insertions(+)
create mode 100644 1224/Immer.md
diff --git a/1224/Immer.md b/1224/Immer.md
new file mode 100644
index 00000000..68a50b08
--- /dev/null
+++ b/1224/Immer.md
@@ -0,0 +1,736 @@
+模板版本:v0.1.3
+
+
+
immer
+
+
+
+
+
+
+
+
+
+> [!TIP] [Github 地址](https://github.com/immerjs/immer)
+
+## 安装与使用
+
+进入到工程目录并输入以下命令:
+
+>[!TIP] # 处替换为 tgz 包的路径
+
+
+
+#### **npm**
+
+```bash
+npm immer@10.0.3
+```
+
+#### **yarn**
+
+```bash
+yarn add immer@10.0.3
+```
+
+
+
+下面的代码展示了这个库的基本使用场景:
+
+```js
+import React, {useState, useEffect} from 'react';
+import {View, Text, Button, StyleSheet, ScrollView} from 'react-native';
+import {
+ createDraft,
+ finishDraft,
+ current,
+ produce,
+ original,
+ isDraft,
+ enablePatches,
+ produceWithPatches,
+ enableMapSet,
+ freeze,
+ nothing,
+ setAutoFreeze,
+ isDraftable,
+ immerable,
+ Immutable,
+ castImmutable,
+ castDraft,
+ applyPatches,
+} from 'immer';
+
+// 初始状态
+const initialState = {
+ count: 0,
+ text: 'Hello from Immer!',
+};
+enablePatches();
+// 启用enablePatches插件
+enableMapSet();
+// 启用enableMapSet插件
+class ShowComponent extends React.Component {
+ state = {
+ mapData: new Map(),
+ setData: new Set(),
+ };
+
+ updateData = () => {
+ this.setState(
+ produce(draft => {
+ draft.mapData.set('key', 'value');
+ draft.setData.add('new item');
+ }),
+ );
+ };
+
+ render() {
+ return (
+
+
+ Map Data: {Array.from(this.state.mapData)}
+ Set Data: {Array.from(this.state.setData)}
+
+ );
+ }
+}
+const MyComponent = () => {
+ let [states, setStates] = useState(false);
+ const [originals, setOriginals] = useState({users: [{name: 'zhansan'}]});
+ let [res, setRes] = useState('');
+ let [currentText, setCurrent] = useState('');
+ // ----------------------------------------------------
+ const [count, setCount] = useState({age: 0});
+ let [baseState, setBaseState] = useState([
+ {
+ title: '标题1',
+ done: true,
+ },
+ ]);
+ const [text, setText] = useState('Hello');
+ let [result, setResult] = useState({});
+ let [patches, setPatches] = useState({});
+ let [inversePatches, setInversePatches] = useState({});
+ const incrementCount = () => {
+ if (count.age < 3) {
+ setCount(
+ produce(count, draft => {
+ draft.age += 1;
+ }),
+ );
+ } else {
+ setCount(
+ produce(count, draft => {
+ draft.age = 0;
+ }),
+ );
+ }
+ };
+ const decrement = () => {
+ if (count.age > 0) {
+ setCount(
+ produce(count, draft => {
+ draft.age -= 1;
+ }),
+ );
+ } else {
+ setCount(
+ produce(count, draft => {
+ draft.age = 3;
+ }),
+ );
+ }
+ };
+ const onAdd = () => {
+ if (baseState.length < 3) {
+ return setBaseState(
+ produce(baseState, draftState => {
+ draftState.push({title: '新增', done: false});
+ }),
+ );
+ }
+ };
+ const onDelete = (e: number) => {
+ return setBaseState(
+ produce(draft => {
+ draft.splice(e, 1);
+ }),
+ );
+ };
+ const onChange = (item: object, e: number) => {
+ const res = produce(baseState, draftState => {
+ draftState[e].done = !draftState[e].done;
+ draftState[e].title = '更改后数据';
+ setStates((states = isDraft(draftState)));
+ });
+ setBaseState(res);
+ };
+ // ----------------------------------------------------
+ const [state, setState] = useState(initialState);
+ // 使用createDraft来创建一个草稿副本
+ const increment = () => {
+ const draft = createDraft(state);
+ draft.count += 1; // 修改草稿副本
+ // setCurrent(current(draft.count))
+ const nextState = finishDraft(draft); // 获取修改后的不可变状态
+ setState(nextState); // 更新React状态
+ };
+
+ const changeText = () => {
+ const draft = createDraft(state);
+ draft.text = 'Text updated!'; // 修改草稿副本
+ const nextState = current(draft); // 获取当前修改后的状态(与finishDraft效果相同)
+ setState(nextState); // 更新React状态
+ };
+ const clickOriginal = () => {
+ const a = setOriginals(
+ produce(originals, draft => {
+ draft.users[0].name = '4444';
+ setCurrent(current(draft).users[0].name);
+ console.log('Original state:', original(draft)?.users[0].name); // 输出原始状态
+ setRes(original(draft).users[0].name);
+ }),
+ );
+ };
+ const handleClick = () => {
+ const [result, patches, inversePatches] = produceWithPatches(
+ text,
+ draft => (draft += ' World'),
+ );
+ setResult(result);
+ setPatches(patches);
+ setInversePatches(inversePatches);
+ console.log('result:', result);
+ console.log('Patches:', patches);
+ console.log('Inverse Patches:', inversePatches);
+
+ setText(result);
+ };
+ // ---------------------------------------------------------
+ const [stateLeft, setStateLeft] = useState([
+ {count: 0},
+ {age: 17, name: 'zhansan'},
+ ]);
+ const [stateRight, setStateRight] = useState([
+ {count: 0},
+ {age: 17, name: 'zhansan'},
+ ]);
+ const [stateRes, setStateRes] = useState({count: 0});
+ const [stateNothing, setStateNothing] = useState({
+ name: 'John',
+ age: 30,
+ isStudent: false,
+ });
+ const [isDraftableList, setIsDraftableList] = useState({
+ one: false,
+ two: false,
+ three: false,
+ });
+ class MyComponent extends React.Component {
+ constructor(props) {
+ super(props);
+
+ // 设置immerable标志
+ this[immerable] = true;
+
+ this.state = {
+ data: {
+ count: 0,
+ text: 'Hello Immer!',
+ immerable: true,
+ },
+ };
+ }
+
+ incrementCount = () => {
+ this.setState(
+ produce(draft => {
+ draft.data.count += 1;
+ draft.data.text = 'hahhaha';
+ }),
+ );
+ };
+
+ render() {
+ return (
+
+ Count: {this.state.data.count}
+ text: {this.state.data.text}
+
+
+ );
+ }
+ }
+ const [counter, setCounter] = useState>(0);
+ // 在组件挂载时设置 immer 的自动冻结行为
+ useEffect(() => {
+ // 启用自动冻结
+ setAutoFreeze(true);
+
+ // 清理函数(可选),在这里我们不需要做任何清理工作
+ return () => {
+ // 如果需要,可以在这里禁用自动冻结
+ setAutoFreeze(false);
+ };
+ }, []); // 空依赖数组确保此 effect 只运行一次
+ // 使用 immer 的 freeze 函数来冻结状态对象
+ freeze(stateLeft, true);
+ freeze(stateRight, false);
+ // 尝试修改冻结的对象将会失败,并且不会触发组件的重新渲染
+ const tryToModifyFrozenStateLeft = () => {
+ try {
+ setStateRight(
+ produce(pradft => {
+ pradft[0].age = 20;
+ pradft[0].name = 'Lisi';
+ }),
+ );
+ } catch (error) {
+ console.error('Error modifying frozen state:', error);
+ }
+ };
+ const tryToModifyFrozenStateRight = () => {
+ try {
+ setStateRight(
+ produce(pradft => {
+ pradft[1].age = 20;
+ pradft[1].name = 'Lisi';
+ }),
+ );
+ } catch (error) {
+ console.error('Error modifying frozen state:', error);
+ }
+ };
+ const incrementCountLeft = () => {
+ // 使用 setState 来安全地更新状态
+ // setState(prevState => ({state[0].count: prevState[0].count + 1}));
+ setStateLeft(
+ produce(stateLeft, prevState => {
+ prevState[0].count += 1;
+ }),
+ );
+ };
+ const incrementCountRight = () => {
+ // 使用 setState 来安全地更新状态
+ setStateRight(
+ produce(stateRight, prevState => {
+ prevState[0].count += 1;
+ }),
+ );
+ };
+ const ClickincrementCount = () => {
+ // 使用 immer 的 produce 函数来安全地更新状态
+ const nextState = produce(stateRes, draft => {
+ draft.count += 1;
+ });
+ // 由于启用了自动冻结,nextState 现在是一个不可变对象
+ try {
+ // 尝试修改 nextState 将会失败,因为它已经被冻结了
+ nextState.count = 100; // 这会抛出错误,因为 nextState 是不可变的
+ } catch (error) {
+ console.error('Error modifying frozen state:', error);
+ }
+
+ setStateRes(nextState);
+ };
+ const removeProperty = () => {
+ const nextStateNothing = produce(stateNothing, draft => {
+ draft.name = 'wangwu';
+ // 使用 nothing 来删除 age 属性
+ delete draft.age; // 传统的删除方法
+ // 或者使用 immer 的 nothing 来达到相同的效果
+ // draft.isStudent = nothing; // 这将删除 isStudent 属性
+ });
+ setStateNothing(nextStateNothing);
+ console.log('stateNothing:', stateNothing);
+ console.log('nextStateNothing:', typeof nextStateNothing.isStudent);
+ };
+ /* useEffect(() => {
+ console.log('Current state:', stateLeft);
+ }, [stateLeft]); */
+ const clickNothing = () => {
+ const nextStateNothing = produce(stateNothing, draft => {
+ draft.name = 'wangwu';
+ // 使用 nothing 来删除 age 属性
+ // 或者使用 immer 的 nothing 来达到相同的效果
+ draft.isStudent = nothing; // 这将删除 isStudent 属性
+ });
+ setStateNothing(nextStateNothing);
+ console.log('stateNothing:', stateNothing);
+ console.log('nextStateNothing:', typeof nextStateNothing.isStudent);
+ };
+ const checkDraftability = () => {
+ const arr = {
+ one: isDraftable(stateRes),
+ two: isDraftable('Hello, World!'),
+ three: isDraftable(42),
+ };
+ setIsDraftableList(arr);
+ console.log('Is state draftable?', isDraftable(stateRes)); // 应该输出 true
+ console.log('Is string draftable?', isDraftable('Hello, World!')); // 应该输出 false
+ console.log('Is number draftable?', isDraftable(42)); // 应该输出 false
+ // ... 可以检查其他类型的值
+ };
+ const incrementCounter = () => {
+ setCounter(produce(counter, draftCounter => (draftCounter += 10)));
+ };
+ // ------------------------------分割线--------------------------------------------------------------------
+ const [data, setData] = useState({name: 'John', age: 30});
+ const [produceStatus, setProduceStatus] = useState(false);
+ const [castDraftState, setCastDraftState] = useState({
+ count: 0,
+ });
+ const updateData = () => {
+ let newData = {};
+ if (!produceStatus) {
+ newData = produce(data, draft => {
+ draft.age += 1;
+ });
+ } else {
+ newData = castImmutable(data, draft => {
+ draft.age += 1;
+ });
+ }
+
+ setData(newData);
+ console.log('newData:', newData);
+ };
+ const Clickfn = () => {
+ setProduceStatus(!produceStatus);
+ };
+ const AddFn = () => {
+ // 使用immer的produce函数来创建一个新的状态副本
+ const newState = produce(castDraftState, draftState => {
+ // 在新状态副本中增加count的值
+ draftState.count += 1;
+ });
+
+ // 使用castDraft函数确保新状态与原始状态不共享内存
+ const nextState = castDraft(newState);
+ // 更新状态
+ setCastDraftState(nextState);
+ };
+ // ---------------分割--start-----------
+ let originalRes = {
+ name: '初始数据1',
+ age: 18,
+ };
+ let fork = originalRes;
+ // 用户在向导中所作的所有更改
+ let changes = [];
+ // 与向导中所做的所有更改相反
+ let inverseChanges = [];
+ let [obj1, setObj1] = useState({});
+ let [obj2, setObj2] = useState({});
+ const ClickChange = () => {
+ fork = produce(
+ fork,
+ draft => {
+ draft.age = 20;
+ },
+ // 产生的第三个参数是一个回调,patches 将从这里产生
+ (patches, inversePatches) => {
+ changes.push(...patches);
+ inverseChanges.push(...inversePatches);
+ },
+ );
+ // 同时,我们的原始状态被替换,例如
+ // 从服务器收到了一些更改
+ originalRes = produce(originalRes, draft => {
+ draft.name = '更改后数据';
+ });
+ };
+ const fn1 = () => {
+ // 当向导完成(成功)后,我们可以将 fork 中的更改重播到新的状态!
+ let originalRes2 = applyPatches(originalRes, changes);
+ setObj1(originalRes2);
+ };
+ const fn2 = () => {
+ // state 现在包含来自两个代码路径的更改!
+ // 最后,即使在完成向导之后,用户也可能会改变主意并撤消他的更改......
+ let originalRes3 = applyPatches(originalRes, inverseChanges);
+ setObj2(originalRes3);
+ };
+
+ // ----------------分割 end-------------
+ return (
+
+
+ Immer
+ {/* 验证---produce---api */}
+
+ 验证-produce-期望值不可变数据可以更改
+
+
+ Count: {count.age}
+
+
+
+
+ {baseState.map((item, index) => (
+
+
+ 标题:{item.title}
+ 状态:{item.done ? 'true' : 'false'}
+ isDraft状态:{`${states}`}
+
+
+
+
+ ))}
+
+
+ {/* --------验证----createDraft--&--finishDraft---------------- */}
+
+ 验证createDraft--&--finishDraft
+ Count: {state.count}
+ Text: {state.text}
+
+
+
+ {/* -----------------验证--original-------current--------------- */}
+
+
+ 验证original--current--期望值验证original:获取修改后的原始状态
+
+ 初始数据:{JSON.stringify(originals)}
+ original:{res}
+ res:{originals.users[0].name}
+ current: {currentText}
+
+
+ {/* ------enablePatches-----produceWithPatches------------------ */}
+
+ 验证enablePatches--produceWithPatches
+ {text}
+ result:{JSON.stringify(result)}
+ patches:{JSON.stringify(patches)}
+ inversePatches:{JSON.stringify(inversePatches)}
+
+
+ {/* ----------验证--enableMapSet------------------------------- */}
+
+ 验证enableMapSet
+ 123
+
+ {/* ------------------------------------- */}
+ {/* -----------------验证--freeze----------------------- */}
+
+ 验证freeze
+
+
+
+ freez开
+
+ Count: {stateLeft[0].count}
+ age: {stateLeft[1].age}
+ name: {stateLeft[1].name}
+
+
+
+
+
+
+ freez关
+
+ Count: {stateRight[0].count}
+ age: {stateRight[1].age}
+ name: {stateRight[1].name}
+
+
+
+
+
+
+ {/* --------------验证--setAutoFreeze------------------- */}
+
+ ---验证setAutoFreeze----
+ setAutoFreeze为自动冻结,默认为true
+ Current Count: {stateRes.count}
+
+
+ {/* --------------验证---nothing------------------------ */}
+
+ 验证nothing
+ Name: {stateNothing.name}
+ {stateNothing.age !== undefined ? (
+ Age: {stateNothing.age}
+ ) : null}
+ {typeof stateNothing.isStudent == 'boolean' ? (
+ Is Student: {stateNothing.isStudent ? 'Yes' : 'No'}
+ ) : null}
+
+
+ 期望age属性删除
+
+
+
+ 期望is student属性删除
+
+
+
+
+ {/* -----------验证----isDraftable---------------------- */}
+
+ 验证isDraftable
+
+ state:{isDraftableList.one ? 'true' : 'false'}----期望值为true
+
+
+ Hello, World:{isDraftableList.two ? 'true' : 'false'}----期望值false
+
+
+ 42:{isDraftableList.three ? 'true' : 'false'}----期望值false
+
+
+
+ {/* -----------验证---immerable-------------------- */}
+
+ 验证---immerable,期望可以改变值
+
+
+ {/* ----------------验证---Immutable----------- */}
+
+ 验证--Immutable--
+ Counter: {counter}
+
+
+ {/* -----------------验证--castImmutable----------------------- */}
+
+ 验证castImmutable
+ castImmutable,期望值castImmutable为true时数据不可变
+ castImmutable:{produceStatus ? 'true' : 'false'}
+
+ Age: {data.age}
+
+
+ {/* -------------------验证--castDraft--- */}
+
+ 验证castDraft
+
+ castDraft,期望值使用castDraft函数确保新状态与原始状态不共享内存
+
+ Count: {castDraftState.count}
+
+
+ {/* ---------------验证--applyPatches-------------- */}
+
+ 验证applyPatches
+ 初始数据:{JSON.stringify(originalRes)}
+
+
+ 改变后数据:{JSON.stringify(obj1)}
+
+ 恢复的数据--{JSON.stringify(obj2)}
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ width: '100%',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 10,
+ marginBottom: 5,
+ borderWidth: 1,
+ },
+ text: {
+ width: '100%',
+ fontSize: 18,
+ marginBottom: 0,
+ textAlign: 'center',
+ fontWeight: '700',
+ margin: 5,
+ },
+ border: {
+ borderWidth: 1,
+ },
+});
+
+export default MyComponent;
+
+```
+
+## 兼容性
+
+在以下版本验证通过
+
+1. RNOH:0.72.13; SDK:HarmonyOS NEXT Developer Preview1; IDE:DevEco Studio 4.1.3.500; ROM:204.1.0.59;
+
+## API
+
+> | Name | Description | Required | Platform | HarmonyOS Support |
+> | ------------------------- | ------------------------------------------------------------ | -------- | ----------- | ----------------- |
+> | `(default)` | Immer 核心 API,通常命名为 `produce`: `import {produce} from "immer"` | NO | Android IOS | YES |
+> | `applyPatches` | 给定一个基本 state 或 draft,以及一组 patches ,应用 patches | NO | Android IOS | YES |
+> | `castDraft` | 将任何不可变类型转换为其可变对应物。这只是一个转换,实际上并没有做任何事情。 | NO | Android IOS | YES |
+> | `castImmutable` | 将任何可变类型转换为其不可变对应物。这只是一个转换,实际上并没有做任何事情。 | NO | Android IOS | YES |
+> | `createDraft` | 给定一个基本 state,创建一个可变 draft,任何修改都将被记录下来 | NO | Android IOS | YES |
+> | `current` | 给定一个 draft 对象(不必是对象的根结点),对 draft 的当前状态进行快照 | NO | Android IOS | YES |
+> | `Draft` | 暴露的 TypeScript 类型以将不可变类型转换为可变类型 | NO | Android IOS | YES |
+> | `enableMapSet()` | 启用对 `Map` 和 `Set` 集合的支持。 | NO | Android IOS | YES |
+> | `enablePatches()` | 启用对 JSON patches 的支持 | NO | Android IOS | YES |
+> | `finishDraft` | 给定使用 `createDraft` 创建的 draft,冻结 draft 并生成并返回下一个不可变状态,该状态捕获所有更改 | NO | Android IOS | YES |
+> | `freeze(obj, deep?)` | 冻结可 draft 对象。返回原始对象。默认情况下浅冻结,但如果第二个参数为真,它将递归冻结。 | NO | Android IOS | YES |
+> | `Immer` | 可用于创建第二个“immer”实例(暴露此实例中列出的所有 API)的构造函数,它不与全局实例共享其设置 | NO | Android IOS | YES |
+> | `immerable` | 可以添加到构造函数或原型的符号,表示 Immer 应该将类视为可以安全 draft 的东西 | NO | Android IOS | YES |
+> | `Immutable` | 暴露的 TypeScript 类型以将可变类型转换为不可变类型 | NO | Android IOS | YES |
+> | `isDraft` | 如果给定对象是 draft 对象,则返回 true | NO | Android IOS | YES |
+> | `isDraftable` | 如果 Immer 能够将此对象变成 draft,则返回 true。这适用于:数组、没有原型的对象、以 `Object` 为原型的对象、在其构造函数或原型上具有 `immerable` 符号的对象 | NO | Android IOS | YES |
+> | `nothing` | 可以从 recipe 返回的值,以指示应生成 `undefined` | NO | Android IOS | YES |
+> | `original` | 给定一个 draft 对象(不必是对象的根结点),返回原始状态树中相同路径的原始对象(如果存在) | NO | Android IOS | YES |
+> | `Patch` | 暴露的 TypeScript 类型,描述(反向)patches 对象的形状 | NO | Android IOS | YES |
+> | `produce` | Immer 的核心 API,也暴露为 `default` 导出 | NO | Android IOS | YES |
+> | `produceWithPatches` | 与 `produce` 相同,但它不仅返回生成的对象,还返回一个由 `[result, patch, inversePatches]` 组成的元组 | NO | Android IOS | YES |
+> | `setAutoFreeze` | 启用/禁用递归的自动冻结。默认启用 | NO | Android IOS | YES |
+> | `setUseStrictShallowCopy` | 可用于启用严格浅拷贝,如果启用,immer将尽可能多地复制不可枚举属性 | NO | Android IOS | YES |
+
+## 遗留问题
+
+## 其他
--
Gitee
From 5ca4e8754590b42f41efaa25c160fd86cb5cffb0 Mon Sep 17 00:00:00 2001
From: yujiang <287650464@qq.com>
Date: Fri, 29 Mar 2024 14:51:45 +0800
Subject: [PATCH 10/10] =?UTF-8?q?[Issues:=20#I99Y71]=20=E6=B7=BB=E5=8A=A0i?=
=?UTF-8?q?mmer=E6=93=8D=E4=BD=9C=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
1224/Immer.md | 648 ++++++++++++++++++++++++++++----------------------
1 file changed, 361 insertions(+), 287 deletions(-)
diff --git a/1224/Immer.md b/1224/Immer.md
index 68a50b08..e6f6f82f 100644
--- a/1224/Immer.md
+++ b/1224/Immer.md
@@ -24,13 +24,13 @@
#### **npm**
```bash
-npm immer@10.0.3
+npm immer
```
#### **yarn**
```bash
-yarn add immer@10.0.3
+yarn add immer
```
@@ -38,8 +38,16 @@ yarn add immer@10.0.3
下面的代码展示了这个库的基本使用场景:
```js
-import React, {useState, useEffect} from 'react';
-import {View, Text, Button, StyleSheet, ScrollView} from 'react-native';
+import React, {useState, useEffect, Component} from 'react';
+import {
+ View,
+ Text,
+ Button,
+ StyleSheet,
+ ScrollView,
+ Switch,
+ TextInput,
+} from 'react-native';
import {
createDraft,
finishDraft,
@@ -59,6 +67,7 @@ import {
castImmutable,
castDraft,
applyPatches,
+ setUseStrictShallowCopy,
} from 'immer';
// 初始状态
@@ -67,40 +76,22 @@ const initialState = {
text: 'Hello from Immer!',
};
enablePatches();
+
// 启用enablePatches插件
enableMapSet();
// 启用enableMapSet插件
-class ShowComponent extends React.Component {
- state = {
- mapData: new Map(),
- setData: new Set(),
- };
+setUseStrictShallowCopy(true);
- updateData = () => {
- this.setState(
- produce(draft => {
- draft.mapData.set('key', 'value');
- draft.setData.add('new item');
- }),
- );
- };
-
- render() {
- return (
-
-
- Map Data: {Array.from(this.state.mapData)}
- Set Data: {Array.from(this.state.setData)}
-
- );
- }
-}
const MyComponent = () => {
+ const [myMap, setMyMap] = useState(new Map([['key1', 'value1']]));
+ const [overStates, setOverStates] = useState(false);
+ const toggleSwitch = value => {
+ setOverStates(value);
+ };
let [states, setStates] = useState(false);
const [originals, setOriginals] = useState({users: [{name: 'zhansan'}]});
let [res, setRes] = useState('');
let [currentText, setCurrent] = useState('');
- // ----------------------------------------------------
const [count, setCount] = useState({age: 0});
let [baseState, setBaseState] = useState([
{
@@ -112,6 +103,41 @@ const MyComponent = () => {
let [result, setResult] = useState({});
let [patches, setPatches] = useState({});
let [inversePatches, setInversePatches] = useState({});
+ const [data, setData] = useState({name: 'John', age: 30});
+ const [produceStatus, setProduceStatus] = useState(false);
+ const [castDraftState, setCastDraftState] = useState({
+ count: 0,
+ });
+ const [state, setState] = useState(initialState);
+ const [freezeRest, setFreezeRest] = useState({a: 1, b: {c: 2}});
+ const [stateRes, setStateRes] = useState({count: 0, text: 'hello-world'});
+ const [texts, setTexts] = useState('请输入内容');
+ const [stateNothing, setStateNothing] = useState({
+ name: 'John',
+ age: 30,
+ isStudent: false,
+ });
+ const obj = {a: 1, b: 2};
+ const arr = [1, 2, 3];
+ const str = 'Hello, immer!';
+ const num = 42;
+ const frozenObj = freeze({c: 3}, true);
+ const [objStatus, setObjStatus] = useState(false);
+ const [arrStatus, setArrStatus] = useState(false);
+ const [strStatus, setStrStatus] = useState(false);
+ const [numStatus, setNumStatus] = useState(false);
+ const [draftsStatus, setDratfStatus] = useState(false);
+ let originalRes = {
+ name: '初始数据1',
+ age: 18,
+ };
+ let fork = originalRes;
+ // 用户在向导中所作的所有更改
+ let changes = [];
+ // 与向导中所做的所有更改相反
+ let inverseChanges = [];
+ let [obj1, setObj1] = useState({});
+ let [obj2, setObj2] = useState({});
const incrementCount = () => {
if (count.age < 3) {
setCount(
@@ -146,7 +172,8 @@ const MyComponent = () => {
if (baseState.length < 3) {
return setBaseState(
produce(baseState, draftState => {
- draftState.push({title: '新增', done: false});
+ draftState.push({title: '新增', done: states});
+ setStates((states = isDraft(draftState)));
}),
);
}
@@ -166,17 +193,33 @@ const MyComponent = () => {
});
setBaseState(res);
};
- // ----------------------------------------------------
- const [state, setState] = useState(initialState);
// 使用createDraft来创建一个草稿副本
const increment = () => {
const draft = createDraft(state);
- draft.count += 1; // 修改草稿副本
- // setCurrent(current(draft.count))
+ if (state.count < 5) {
+ draft.count += 1; // 修改草稿副本
+ } else {
+ draft.count = 0;
+ }
const nextState = finishDraft(draft); // 获取修改后的不可变状态
setState(nextState); // 更新React状态
};
-
+ const updateMap = () => {
+ setMyMap(
+ produce(myMap, draftMap => {
+ draftMap.set('key1', 'updatedValue1'); // 更新键值对
+ draftMap.set('key2', 'value2'); // 添加新的键值对
+ draftMap.delete('key3'); // 尝试删除一个不存在的键值对(不会有影响)
+ }),
+ );
+ };
+ const renderMapEntries = () => {
+ return Array.from(myMap.entries()).map(([key, value]) => (
+
+ {key}: {value}
+
+ ));
+ };
const changeText = () => {
const draft = createDraft(state);
draft.text = 'Text updated!'; // 修改草稿副本
@@ -196,7 +239,7 @@ const MyComponent = () => {
const handleClick = () => {
const [result, patches, inversePatches] = produceWithPatches(
text,
- draft => (draft += ' World'),
+ draft => (draft = 'Hello-World'),
);
setResult(result);
setPatches(patches);
@@ -207,185 +250,120 @@ const MyComponent = () => {
setText(result);
};
- // ---------------------------------------------------------
- const [stateLeft, setStateLeft] = useState([
- {count: 0},
- {age: 17, name: 'zhansan'},
- ]);
- const [stateRight, setStateRight] = useState([
- {count: 0},
- {age: 17, name: 'zhansan'},
- ]);
- const [stateRes, setStateRes] = useState({count: 0});
- const [stateNothing, setStateNothing] = useState({
- name: 'John',
- age: 30,
- isStudent: false,
- });
- const [isDraftableList, setIsDraftableList] = useState({
- one: false,
- two: false,
- three: false,
- });
- class MyComponent extends React.Component {
- constructor(props) {
- super(props);
-
- // 设置immerable标志
- this[immerable] = true;
-
- this.state = {
- data: {
- count: 0,
- text: 'Hello Immer!',
- immerable: true,
- },
- };
- }
-
- incrementCount = () => {
- this.setState(
- produce(draft => {
- draft.data.count += 1;
- draft.data.text = 'hahhaha';
- }),
- );
- };
-
- render() {
- return (
-
- Count: {this.state.data.count}
- text: {this.state.data.text}
-
-
- );
+ // -----------------------------------------------
+ class MyImmerableObject extends React.Component {
+ // 声明immerable属性,告诉immer处理哪些属性
+ static [immerable] = true;
+ // 定义您的对象的属性
+ constructor(name, age) {
+ super(name, age);
+ this.name = name;
+ this.age = age;
}
+ /* // 不使用immerable
+ // 声明immerable属性,告诉immer处理哪些属性
+ static [immerable] = true;
+ // 定义您的对象的属性
+ constructor(name, age) {
+ super(name, age);
+ this.name = name;
+ this.age = age;
+ } */
}
- const [counter, setCounter] = useState>(0);
+ const [myState, setMyState] = useState(new MyImmerableObject('Alice', 10));
+ const updateValue = () => {
+ // 使用immerable
+ const res = produce(myState, draft => {
+ draft.age = 26;
+ });
+ /* // 不使用immerable
+ const res = {...myState, age: 26}; */
+ setMyState(res);
+ };
// 在组件挂载时设置 immer 的自动冻结行为
useEffect(() => {
- // 启用自动冻结
- setAutoFreeze(true);
-
- // 清理函数(可选),在这里我们不需要做任何清理工作
- return () => {
- // 如果需要,可以在这里禁用自动冻结
- setAutoFreeze(false);
- };
- }, []); // 空依赖数组确保此 effect 只运行一次
- // 使用 immer 的 freeze 函数来冻结状态对象
- freeze(stateLeft, true);
- freeze(stateRight, false);
- // 尝试修改冻结的对象将会失败,并且不会触发组件的重新渲染
- const tryToModifyFrozenStateLeft = () => {
- try {
- setStateRight(
- produce(pradft => {
- pradft[0].age = 20;
- pradft[0].name = 'Lisi';
- }),
- );
- } catch (error) {
- console.error('Error modifying frozen state:', error);
- }
+ // 启用/停用自动冻结
+ setAutoFreeze(overStates);
+ }, [overStates]); // 空依赖数组确保此 effect 只运行一次
+ const incrementCountLeft = () => {
+ const res = freeze(Object.assign({}, freezeRest), true);
+ res.a = 110;
+ res.b.c = 220;
+ console.log('调用freeze-deep:', overStates, res);
+ setFreezeRest(res);
};
- const tryToModifyFrozenStateRight = () => {
- try {
- setStateRight(
- produce(pradft => {
- pradft[1].age = 20;
- pradft[1].name = 'Lisi';
- }),
- );
- } catch (error) {
- console.error('Error modifying frozen state:', error);
- }
+ const tryToModifyFrozenStateLeft = () => {
+ const res = freeze(Object.assign({}, freezeRest), false);
+ res.a = 111;
+ res.b.c = 222;
+ console.log('调用freeze-deep:', overStates, res);
+ setFreezeRest(res);
};
- const incrementCountLeft = () => {
- // 使用 setState 来安全地更新状态
- // setState(prevState => ({state[0].count: prevState[0].count + 1}));
- setStateLeft(
- produce(stateLeft, prevState => {
- prevState[0].count += 1;
- }),
- );
+ const ClickOffFreeze = () => {
+ const res1 = Object.assign({}, freezeRest);
+ res1.a = 10;
+ res1.b.c = 20;
+ console.log('未调用freeze:', res);
+ setFreezeRest(res1);
};
- const incrementCountRight = () => {
- // 使用 setState 来安全地更新状态
- setStateRight(
- produce(stateRight, prevState => {
- prevState[0].count += 1;
- }),
- );
+ const ClickOnFreeze = () => {
+ const res = freeze(Object.assign({}, freezeRest));
+ res.a = 11;
+ res.b.c = 22;
+ console.log('调用freeze:', res);
+ setFreezeRest(res);
};
- const ClickincrementCount = () => {
- // 使用 immer 的 produce 函数来安全地更新状态
- const nextState = produce(stateRes, draft => {
- draft.count += 1;
- });
- // 由于启用了自动冻结,nextState 现在是一个不可变对象
- try {
- // 尝试修改 nextState 将会失败,因为它已经被冻结了
- nextState.count = 100; // 这会抛出错误,因为 nextState 是不可变的
- } catch (error) {
- console.error('Error modifying frozen state:', error);
- }
-
+ const inputText = e => {
+ let nextState = produce(stateRes, draft => {});
+ setTexts(e);
+ nextState.text = e;
setStateRes(nextState);
};
- const removeProperty = () => {
- const nextStateNothing = produce(stateNothing, draft => {
- draft.name = 'wangwu';
- // 使用 nothing 来删除 age 属性
- delete draft.age; // 传统的删除方法
- // 或者使用 immer 的 nothing 来达到相同的效果
- // draft.isStudent = nothing; // 这将删除 isStudent 属性
- });
+ const clickNothing = e => {
+ const nextStateNothing = produce(stateNothing, draft => e);
setStateNothing(nextStateNothing);
- console.log('stateNothing:', stateNothing);
- console.log('nextStateNothing:', typeof nextStateNothing.isStudent);
- };
- /* useEffect(() => {
- console.log('Current state:', stateLeft);
- }, [stateLeft]); */
- const clickNothing = () => {
- const nextStateNothing = produce(stateNothing, draft => {
- draft.name = 'wangwu';
- // 使用 nothing 来删除 age 属性
- // 或者使用 immer 的 nothing 来达到相同的效果
- draft.isStudent = nothing; // 这将删除 isStudent 属性
- });
- setStateNothing(nextStateNothing);
- console.log('stateNothing:', stateNothing);
- console.log('nextStateNothing:', typeof nextStateNothing.isStudent);
- };
- const checkDraftability = () => {
- const arr = {
- one: isDraftable(stateRes),
- two: isDraftable('Hello, World!'),
- three: isDraftable(42),
- };
- setIsDraftableList(arr);
- console.log('Is state draftable?', isDraftable(stateRes)); // 应该输出 true
- console.log('Is string draftable?', isDraftable('Hello, World!')); // 应该输出 false
- console.log('Is number draftable?', isDraftable(42)); // 应该输出 false
- // ... 可以检查其他类型的值
- };
- const incrementCounter = () => {
- setCounter(produce(counter, draftCounter => (draftCounter += 10)));
- };
- // ------------------------------分割线--------------------------------------------------------------------
- const [data, setData] = useState({name: 'John', age: 30});
- const [produceStatus, setProduceStatus] = useState(false);
- const [castDraftState, setCastDraftState] = useState({
- count: 0,
+ };
+ const isDraftObj = () => {
+ setObjStatus(isDraftable(obj));
+ };
+ const isDraftArr = () => {
+ setArrStatus(isDraftable(arr));
+ };
+ const isDraftStr = () => {
+ setStrStatus(isDraftable(str));
+ };
+ const isDraftNum = () => {
+ setNumStatus(isDraftable(num));
+ };
+ const isDrafts = () => {
+ setDratfStatus(isDraftable(frozenObj));
+ };
+ // --------------------------------------------
+ const [draftRes, setDraftRes] = useState({
+ name: 'John',
+ age: 30,
+ hobbies: ['reading', 'coding'],
});
+
+ const [setUseStrictShallowCopyRes, setSetUseStrictShallowCopyRes] = useState({
+ name: 'John',
+ age: 30,
+ address: {
+ city: 'New York',
+ country: 'USA',
+ },
+ });
+ const [setUseStrictShallowCopyInit, setSetUseStrictShallowCopyInit] =
+ useState();
const updateData = () => {
let newData = {};
if (!produceStatus) {
newData = produce(data, draft => {
- draft.age += 1;
+ if (draft.age < 40) {
+ draft.age += 1;
+ } else {
+ draft.age = 0;
+ }
});
} else {
newData = castImmutable(data, draft => {
@@ -394,40 +372,42 @@ const MyComponent = () => {
}
setData(newData);
- console.log('newData:', newData);
};
const Clickfn = () => {
setProduceStatus(!produceStatus);
};
const AddFn = () => {
- // 使用immer的produce函数来创建一个新的状态副本
- const newState = produce(castDraftState, draftState => {
- // 在新状态副本中增加count的值
- draftState.count += 1;
- });
-
- // 使用castDraft函数确保新状态与原始状态不共享内存
- const nextState = castDraft(newState);
- // 更新状态
- setCastDraftState(nextState);
+ setCastDraftState(
+ produce(castDraftState, draftState => {
+ if (castDraftState.count < 10) {
+ draftState.count += 1;
+ } else {
+ draftState.count = 0;
+ }
+ }),
+ );
};
- // ---------------分割--start-----------
- let originalRes = {
- name: '初始数据1',
- age: 18,
+ const doubleCount = () => {
+ setCastDraftState(
+ produce(castDraftState, draftState => {
+ if (castDraftState.count < 100) {
+ draftState.count *= 2;
+ } else {
+ draftState.count = 0;
+ }
+ }),
+ );
+ };
+ const resetCount = () => {
+ const newState = castDraft({count: 0});
+ setCastDraftState(newState);
};
- let fork = originalRes;
- // 用户在向导中所作的所有更改
- let changes = [];
- // 与向导中所做的所有更改相反
- let inverseChanges = [];
- let [obj1, setObj1] = useState({});
- let [obj2, setObj2] = useState({});
const ClickChange = () => {
fork = produce(
fork,
draft => {
- draft.age = 20;
+ draft.age = 10;
+ draft.name = 'lisi';
},
// 产生的第三个参数是一个回调,patches 将从这里产生
(patches, inversePatches) => {
@@ -435,16 +415,12 @@ const MyComponent = () => {
inverseChanges.push(...inversePatches);
},
);
- // 同时,我们的原始状态被替换,例如
- // 从服务器收到了一些更改
- originalRes = produce(originalRes, draft => {
- draft.name = '更改后数据';
- });
};
const fn1 = () => {
// 当向导完成(成功)后,我们可以将 fork 中的更改重播到新的状态!
let originalRes2 = applyPatches(originalRes, changes);
setObj1(originalRes2);
+ console.log('originalRes2:', originalRes2);
};
const fn2 = () => {
// state 现在包含来自两个代码路径的更改!
@@ -452,6 +428,50 @@ const MyComponent = () => {
let originalRes3 = applyPatches(originalRes, inverseChanges);
setObj2(originalRes3);
};
+ const handleAddHobby = () => {
+ //不使用Draft
+ const newDraftRes = {...draftRes};
+ newDraftRes.hobbies[1] = 'swimming';
+ setDraftRes(newDraftRes);
+ // 使用Draft
+ /* const nextDraftRes = produce(draftRes, draft => {
+ draft.hobbies[1] = 'swimming';
+ });
+ setDraftRes(nextDraftRes); */
+ };
+ interface Person {
+ name: string;
+ age: number;
+ }
+ // 使用Immutable
+ const immutableObj1: Immutable = {
+ name: 'Alice',
+ age: 20,
+ };
+ // 不使用Immutable
+ // const immutableObj1 = {
+ // name: 'Alice',
+ // age: 20,
+ // };
+ const [immutableData, setImmutableData] = useState();
+ const changeObj1 = () => {
+ const res = immutableObj1;
+ res.name = 'lisi';
+ console.log('immutableObj1:', immutableObj1);
+ setImmutableData(res);
+ };
+ const useSetUseStrictShallowCopy = () => {
+ const res = produce(setUseStrictShallowCopyRes, draft => {
+ draft.age = 55;
+ draft.address.city = 'China';
+ });
+ console.log('res:', JSON.stringify(res));
+ console.log(
+ 'setSetUseStrictShallowCopyRes:',
+ JSON.stringify(setUseStrictShallowCopyRes),
+ );
+ setSetUseStrictShallowCopyInit(res);
+ };
// ----------------分割 end-------------
return (
@@ -548,95 +568,118 @@ const MyComponent = () => {
{/* ----------验证--enableMapSet------------------------------- */}
验证enableMapSet
- 123
+ Current Map:
+ {renderMapEntries()}
+
- {/* ------------------------------------- */}
{/* -----------------验证--freeze----------------------- */}
验证freeze
+
+ freeze(obj,deep?)obj:要冻结的对象deep(可选):一个布尔值,默认为false。如果为true,则深度冻结对象(包括其所有嵌套的对象)。如果为false或未提供,则只冻结对象的顶层属性
+
-
- freez开
-
- Count: {stateLeft[0].count}
- age: {stateLeft[1].age}
- name: {stateLeft[1].name}
-
+ init:{JSON.stringify(freezeRest)}
+
+
-
-
-
-
- freez关
-
- Count: {stateRight[0].count}
- age: {stateRight[1].age}
- name: {stateRight[1].name}
-
-
-
+
{/* --------------验证--setAutoFreeze------------------- */}
---验证setAutoFreeze----
- setAutoFreeze为自动冻结,默认为true
- Current Count: {stateRes.count}
-
+
+ setAutoFreeze为自动冻结,状态:{JSON.stringify(overStates)}
+
+
+
+ 你输入的内容是: {stateRes.text}
+ Current Count: {JSON.stringify(stateRes)}
{/* --------------验证---nothing------------------------ */}
验证nothing
- Name: {stateNothing.name}
- {stateNothing.age !== undefined ? (
- Age: {stateNothing.age}
- ) : null}
- {typeof stateNothing.isStudent == 'boolean' ? (
- Is Student: {stateNothing.isStudent ? 'Yes' : 'No'}
- ) : null}
+
+ 定义的数据:
+ {JSON.stringify(stateNothing)}
+
+ Name: {typeof stateNothing}
- 期望age属性删除
-
+ {
+ clickNothing(nothing);
+ }}
+ />
- 期望is student属性删除
-
+ {
+ clickNothing(undefined);
+ }}
+ />
{/* -----------验证----isDraftable---------------------- */}
验证isDraftable
-
- state:{isDraftableList.one ? 'true' : 'false'}----期望值为true
-
-
- Hello, World:{isDraftableList.two ? 'true' : 'false'}----期望值false
-
-
- 42:{isDraftableList.three ? 'true' : 'false'}----期望值false
-
-
+ {/*
+ {result ? '可变对象' : '不可变对象'} */}
+
+ 状态--isDraftable({JSON.stringify(obj)})
+
+ 状态:{JSON.stringify(objStatus)}
+
+
+ 状态--isDraftable({JSON.stringify(arr)})
+
+ 状态--{JSON.stringify(arrStatus)}
+
+
+ 状态--isDraftable({JSON.stringify(str)})
+
+ 状态--{JSON.stringify(strStatus)}
+
+
+ 状态--isDraftable({JSON.stringify(num)})
+
+ 状态--{JSON.stringify(numStatus)}
+
+
+ 状态--isDraftable({JSON.stringify(frozenObj)})
+
+ 状态--{JSON.stringify(draftsStatus)}
+
{/* -----------验证---immerable-------------------- */}
- 验证---immerable,期望可以改变值
-
-
- {/* ----------------验证---Immutable----------- */}
-
- 验证--Immutable--
- Counter: {counter}
-
+
+ 验证---immerable,可以添加到构造函数或原型的符号
+
+ NUM:{JSON.stringify(myState)}
+
{/* -----------------验证--castImmutable----------------------- */}
@@ -651,21 +694,49 @@ const MyComponent = () => {
验证castDraft
- castDraft,期望值使用castDraft函数确保新状态与原始状态不共享内存
+ castDraft,期望将任何不可变类型转换为其可变对应物。这只是一个转换,实际上并没有做任何事情
Count: {castDraftState.count}
-
+
+
+
{/* ---------------验证--applyPatches-------------- */}
验证applyPatches
初始数据:{JSON.stringify(originalRes)}
-
+
改变后数据:{JSON.stringify(obj1)}
恢复的数据--{JSON.stringify(obj2)}
+
+
+ 验证Draft暴露的 TypeScript 类型以将不可变类型转换为可变类型
+
+ {JSON.stringify(draftRes)}
+
+
+ {/* 验证Immutable */}
+ {/*
+
+ 验证Immutable暴露的 TypeScript 类型以将可变类型转换为不可变类型
+
+ 初始数据:{JSON.stringify(immutableObj1)}
+ 更改后数据:{JSON.stringify(immutableData)}
+
+ */}
+ {/* 验证setUseStrictShallowCopy */}
+
+
+ 验证setUseStrictShallowCopy
+ 可用于启用严格浅拷贝,如果启用,immer会确保不会意外的修改原始对象
+
+ 初始数据:{JSON.stringify(setUseStrictShallowCopyRes)}
+ 更改后数据:{JSON.stringify(setUseStrictShallowCopyInit)}
+
+
);
@@ -695,6 +766,7 @@ const styles = StyleSheet.create({
export default MyComponent;
+
```
## 兼容性
@@ -705,6 +777,8 @@ export default MyComponent;
## API
+详情见[Immer](https://immerjs.github.io/immer/zh-CN/api/)
+
> | Name | Description | Required | Platform | HarmonyOS Support |
> | ------------------------- | ------------------------------------------------------------ | -------- | ----------- | ----------------- |
> | `(default)` | Immer 核心 API,通常命名为 `produce`: `import {produce} from "immer"` | NO | Android IOS | YES |
--
Gitee