[React] 即使是 React 初学者也能完全理解“状态管理”(不使用库)

1.首先

我“React 在文件之间来回走,我不懂!”“反应太难了”... 所以我认为。

我写这篇文章是为了组织这个来回的 React 流程。

如果您能帮助有相同想法的人,我将不胜感激。

在本文中,我们将研究“状态管理”。

国家的极好的是基本内容。

* 对于状态管理,不使用useState 以外的钩子和库。

极好的我想看看 state 的值是如何通过简单的内容传递的。

如果您能指出我是否误解了某些内容,我将不胜感激。

2. 内容

   

3.你可以从这篇文章中学到什么

状态的值为

父组件→子组件→孙子组件(从上到下传递状态值) 孙组件→子组件→父组件(从下往上传递状态值)

我会看流量。

接收根组件中的状态值,将值传递给父/子/孙子组件,显示用户信息,单击孙组件的删除按钮,并将更改的状态值传递给子/父组件。

↓ 就是这样一个简单的应用程序。

最终的源代码如下。

本文不包括用于类型定义的src/user.ts 和src/userList.ts 以及用于用户信息的src/user-data.json。另外,src/index.tsx是显示组件的文件,这里也省略说明。关于上面的源代码,如果你能看到这样的定义,我将不胜感激。(如果您复制以下内容,它将起作用。)

src/user.ts(类型定义)
export type User = {
  id: string;
  name: string;
  age: number;
  onRemoveUser?: (id: string) => void;
  onRemove?: (id: string) => void;
};
src/userList.ts(类型定义)
import type { User } from "./user";

export type UserList = {
  users: User[];
  onRemoveUser?: (id: string) => void;
};
src/user-data.json(用户信息)
[
  {
    "id": "dahis1",
    "name": "daishi",
    "age": 10
  },
  {
    "id": "manju2",
    "name": "manju",
    "age": 20
  },
  {
    "id": "daishiman3",
    "name": "daishiman",
    "age": 30
  }
]
src/index.tsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
src/App.tsx(父组件)
import { useState } from "react";
import userData from "./user-data.json";
import { UserList } from "./UserList";
import type { User } from "./user";

export default function App() {
  const [users, setUsers] = useState<User[]>(userData);

  const removeUser = (id: string) => {
    const newUsers = users.filter((user) => user.id !== id);
    setUsers(newUsers);
  };

  return (
    <div>
      <UserList users={users} onRemoveUser={removeUser} />
    </div>
  );
}
src/UserList.tsx(子组件)
import { FC } from "react";
import { User } from "./User";
import type { UserList as UserListType } from "./userList";

export const UserList: FC<UserListType> = ({
  users = [],
  onRemoveUser = (f) => f
}) => {
  if (!users.length) return <div>表示できるユーザーはいません</div>;

  return (
    <div>
      {users.map((user) => (
        <User key={user.id} {...user} onRemove={onRemoveUser} />
      ))}
    </div>
  );
};
src/User.tsx(孙组件)
import { FC } from "react";
import type { User as UserType } from "./user";

export const User: FC<UserType> = ({ 
  id,
  name,
  age,
  onRemove = (f) => f
}) => {
  return (
    <section>
      <p>
        {name}(年齢:{age}歳)
      </p>
      <button onClick={() => onRemove(id)}>削除</button>
    </section>
  );
};
4.环境 反应:17.0.2 打字稿:4.4.2 5.状态管理

我们将看一个管理状态值、显示用户信息和删除它们的简单流程。

父母组件 →孩子组件 →孙子零件(从上到下传递状态值) 孙子组件 →孩子组件 →父母零件(从下到上传递状态值)

我会在流程中查看它。

1.父母组件 →孩子组件 →孙子组件(从上到下传递状态值)

现在,将 src/user-data.json 用户信息从父 (App) 组件传递给孙 (User) 组件并显示用户信息。

2.孙子组件 →孩子组件 →父母组件(从下到上传递状态值)

现在,点击孙子(User)组件的删除按钮,减少显示的状态值的用户信息。

观察这些趋势状态值来回走动我想确认

5.1.从上到下传递状态值

我们先来看看从顶部(父)到底部(孙)传递状态值的流程。

本次使用的源码结构如下。

父组件:src/App.tsx 子组件:src/UserList.tsx 孙子组件:src/User.tsx 5.1.1. 父组件向子组件传递状态值

首先,让我们看一下父 (App) 组件。

src/App.tsx(父组件)
import { useState } from "react";
import userData from "./user-data.json";
import { UserList } from "./UserList";
import type { User } from "./user";

export default function App() {
  const [users] = useState<User[]>(userData);

  return (
    <div>
      <UserList users={users} />
    </div>
  );
}

App组件配置

使用useState 管理状态 将状态管理值 (users) 传递给 UserList 组件 显示UserLIst

它已成为。

让我们仔细看看。

1.用useState进行状态管理

使用useState钩子管理状态值。

(↓useState的参考文章)

变成以下部分。

const [users] = useState<User[]>(userData);

由于我们还没有更新值,所以我们还没有编写更新的函数。

将src/user-data.json 的userData 赋值给变量users 作为初始值。

2.将状态管理值(users)传递给子组件

您正在将变量 users 的值传递给子 (UserList) 组件的 users 属性。

<UserList users={users} />

上面的 UserList 组件定义在以下子 (UserList) 组件中完成:

3.显示UserLIst

src/App.tsx 显示 UserList 组件。

这是传递父 (App) 组件的状态值的流程。

5.1.2. 将状态值从子组件传递给孙子组件

然后将从父 (App) 组件接收到的状态值传递给孙 (User) 组件子 (UserList) 组件我会看看

这次是App.tsx 使用UserList 组件,正如“组件”一词所暗示的那样,UserList 组件可以在各个地方使用。

这就是组件有用的原因。

让我们回过头来看看源代码。

src/UserList.tsx(子组件)
import { FC } from "react";
import { User } from "./User";
import type { UserList as UserListType } from "./userList";

export const UserList: FC<UserListType> = ({
  users = [],
}) => {
  if (!users.length) return <div>表示できるユーザーはいません</div>;

  return (
    <div>
      {users.map((user) => (
        <User key={user.id} {...user} />
      ))}
    </div>
  );
};

UserList 组件由以下部分组成:

UserList是用箭头函数写的(关于箭头函数的参考文章) 参数users = [] 省略users: users = [] users.length 为假时的返回值 (0) users.length 不为假时的返回值 (0) 1.UserList写成箭头函数

起初它可能看起来令人困惑,但将其分解,您会发现它使用箭头函数。

const const UserList: FC<UserListType> = () => {}

UserLIst 组件使用这个↑。

2.users = []在参数中省略users: users = []

users 在UserList 的箭头函数参数中省略了users: users。 (参考文章)因此,users 的值被分配给users 属性。

users 的值为天空[] 默认被替换。

把这些放在一起,

users = [] 与 users: users = [] 相同,并使用缩写符号编写。

3.users.length为假时的返回值(0)
if (!users.length) return <div>表示できるユーザーはいません</div>;

如您所见,当users.length 为假(0)时,

<div>表示できるユーザーはいません</div>;

它显示出来。

4.users.length不为假时的返回值(0)

当users.length 不为假(0)时,

    <div>
      {users.map((user) => (
        <User key={user.id} {...user} />
      ))}
    </div>

过程将起作用。

users 数组通过map 函数转换为User 组件数组并显示。

{...user} 将 user.name 和 user.age 组合在一起,而不是 user.id 并将它们传递给孙子 (User) 组件。

5.1.3. 在孙子组件中接收状态值

最后,我们将看看孙子 (User) 组件。

状态值从父级(App)传递给子级(UserList)和孙级(User),它是如何显示最后传递的值的一个组件。

src/User.tsx(孙组件)
import { FC } from "react";
import type { User as UserType } from "./user";

export const User: FC<UserType> = ({ 
  name,
  age,
}) => {
  return (
    <section>
      <p>
        {name}(年齢:{age}歳)
      </p>
    </section>
  );
};

User组件配置

UserList是用箭头函数写的(关于箭头函数的参考文章) 参数 name 和 age 省略 name: name 和 age: age 显示姓名和年龄

它已成为。

1.UserList写成箭头函数

由于和之前的内容相同,我们省略了细节。

const User: FC<UserType> = () => {};

就是它。

2.参数name和age省略name: name和age: age

由于这里相同,所以省略说明。

name 是 name: name 的缩写 yera 是 yera: age 的缩写 3.显示姓名和年龄

从父组件按顺序传过来的状态值最终显示在这里。

  return (
    <section>
      <p>
        {name}(年齢:{age}歳)
      </p>
    </section>
  );

路很长,我希望你已经掌握了从父(App)组件到孙(User)组件的传递和显示状态值的流程。

接下来,我们看一下在孙(User)组件上定义删除按钮并将要删除的状态值传递给父(App)组件的流程。

5.2.从下往上传递状态值

该实现的概要如下。

在孙子组件中定义删除按钮 将已删除的状态值传播到父组件 更新父组件中的状态 之后,流程和上面传状态值一样

现在让我们将它添加到孙子组件中。

5.2.1. 孙子组件增加删除功能

向孙 (User) 组件添加删除功能。

我们在这里做的是点击查看发生了哪个用户的事件(删除)子 (UserList) 组件是告诉

src/User.tsx(孙组件)
import { FC } from "react";
import type { User as UserType } from "./user";

export const User: FC<UserType> = ({ 
+ id,
  name,
  age,
+ onRemove = (f) => f
}) => {
  return (
    <section>
      <p>
        {name}(年齢:{age}歳)
      </p>
+     <button onClick={() => onRemove(id)}>削除</button>
    </section>
  );
};

让我们看看流程。

删除按钮点击事件被触发 调用onRemove函数删除 onRemove 函数是添加到 User 组件的新属性 onRemove 函数在参数中接收 id 值(知道哪个用户) onRemove 函数接受 id 并返回 id 使用孙 (User) 组件将 id 返回给子 (UserList) 组件

这就是您将状态值从孙 (User) 组件传递给子 (UserList) 组件的方式。

5.2.2.子组件增加删除功能

接下来,添加逻辑以将 id 从孙 (User) 组件传播到父 (App) 组件。

孙子 (User) 组件执行 id 传递到这里。

src/UserList.tsx(子组件)
import { FC } from "react";
import { User } from "./User";
import type { UserList as UserListType } from "./userList";

export const UserList: FC<UserListType> = ({
  users = [],
+ onRemoveUser = (f) => f
}) => {
  if (!users.length) return <div>表示できるユーザーはいません</div>;

  return (
    <div>
      {users.map((user) => (
-       <User key={user.id} {...user} />
+       <User key={user.id} {...user} onRemove={onRemoveUser} />
      ))}
    </div>
  );
};

让我们看看情况如何。

从孙 (User) 组件接收 id 作为 onRemove 属性的值 id 在 1 中收到。分配给 onRemoveUser 函数 onRemoveUser 函数是添加到 UserList 组件的新属性 分配给onRemoveUser 函数的onRemoveUser id 按原样返回id 使用子 (UserList) 组件将 id 返回给父 (App) 组件

流程几乎与我对孙子 (User) 组件所做的相同。

5.2.3. 父组件添加删除功能

最后,向父 (App) 组件添加删除功能。

这里我们需要添加逻辑来更新从子(UserList)传递给父(App)的状态值。

src/App.tsx(父组件)
import { useState } from "react";
import userData from "./user-data.json";
import { UserList } from "./UserList";
import type { User } from "./user";

export default function App() {
- const [users] = useState<User[]>(userData);
+ const [users, setUsers] = useState<User[]>(userData);

+ const removeUser = (id: string) => {
+   const newUsers = users.filter((user) => user.id !== id);
+   setUsers(newUsers);
+ };

  return (
    <div>
-     <UserList users={users} />
+     <UserList users={users} onRemoveUser={removeUser} />
    </div>
  );
}

我们来看看最终的流程。

在useState钩子中添加setUser变量以更新users 从子 (UserList) 组件接收 id 作为 onRemoveUser 属性的值 id 在 1 中收到。分配给 removeUser 函数 removeUser 函数是4.1. 使用filter函数从users数组中提取user.id与id不匹配的用户4.2. 将4.1.中提取的用户赋值给newUsers变量4.3. 将newUsers 传递给setUsers 以更新状态值 users更新为再次从上到下传递状态值 下面重复“从上到下传递状态值”

变成。

最后一个父级 (App) 可能看起来有点复杂,但这就是我们使用 useState 挂钩来管理状态值的方式。

但是,由于状态值是像桶旅一样传递的,所以组件的层数越多,就越复杂。

我想写另一篇关于解决这些问题的钩子和库的文章。

六,结论

状态值

父组件→子组件→孙子组件(从上到下传递状态值) 孙组件→子组件→父组件(从下往上传递状态值)

通过查看传递的流程,我能够掌握 React 的重要状态管理。

但是,我觉得一个个通过状态很麻烦。

这一次,是从父母到孙子,但如果层数多了,就会变得难以管理。

出于这个原因,我认为创建了方便的钩子和库......

未来,我想赶上状态管理钩子和库,成为 React 大师。

感谢您阅读到最后?

如果您也可以阅读其他文章,我会很高兴?‍♂️

7. 参考 开发 React 动手学习 Web 应用程序的最佳实践作者:亚历克斯·班克斯、伊芙·波切洛翻译:宫崎骏 [JavaScript] 对象字面量的简写符号

原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308631506.html

41人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册