From c22b20b3d2fe56e4ff792911f420a89b8943aa14 Mon Sep 17 00:00:00 2001 From: Oblivion <915019672@qq.com> Date: Tue, 28 Jul 2020 17:51:21 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=201.=E5=9C=A8state=E5=A4=96=E6=93=8D?= =?UTF-8?q?=E4=BD=9Cstate=EF=BC=9B2.map=E7=BC=BA=E5=B0=91key=EF=BC=9B3.?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89=EF=BC=9B4.=E8=A1=8C?= =?UTF-8?q?=E5=86=85=E6=A0=B7=E5=BC=8F=E4=BF=AE=E6=AD=A3=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/EventEmitterButton.tsx | 36 +++++++++++----- src/pages/index.tsx | 60 +++++++++++++++++---------- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/components/EventEmitterButton.tsx b/src/components/EventEmitterButton.tsx index 0b15358..c1baa39 100644 --- a/src/components/EventEmitterButton.tsx +++ b/src/components/EventEmitterButton.tsx @@ -1,15 +1,29 @@ -import React, { useState } from 'react'; -import { layoutEmitter } from '@/utils/EventEmitter'; +// import React, { useState, useEffect } from 'react'; +import React, { useState } from "react"; +import { layoutEmitter } from "@/utils/EventEmitter"; -export default ({ initNumber }) => { +interface IState { + initNumber: number; +} - const [state, setstate] = useState(initNumber); +export default ({ initNumber }: IState) => { + const [state, setstate] = useState(initNumber); - return { - setstate(state + 1) - layoutEmitter.emit({ state }); - }} - >EventEmitter {state} + // useEffect(() => { // unfixed: 可以在这里解决,但第一次 this._subscription 未初始化,不是个对象,会报错。 + // layoutEmitter.emit({ state }); + // return () => {} + // }, [state]) + + return ( + { + setstate(state + 1); + layoutEmitter.emit({ state }); // unfixed: 父组件订阅不到初次的状态。 可以 emit({state + 1}),但不想被骂。 + }} + > + EventEmitter {state}{" "} + + ); }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index dd45813..dc5869b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,25 +1,43 @@ -import React, { useEffect, useState } from 'react'; -import { layoutEmitter } from '@/utils/EventEmitter'; -import EventEmitterButton from '@/components/EventEmitterButton'; +import React, { useEffect, useState } from "react"; +import { layoutEmitter } from "@/utils/EventEmitter"; +import EventEmitterButton from "@/components/EventEmitterButton"; + +export interface IStateData { + state: number; +} export default () => { - const [list, setList] = useState([]); + const [list, setList] = useState>([]); + + useEffect(() => { + layoutEmitter.useSubscription((data) => { + // list.push(data); + + // fixed: 不能在 setState 外直接操作 state,react 数据的不可变性。 + // 直接操作 state 会导致之前的变更无效(应该是这个原因),所以 DOM 不会重新渲染。 + + console.log(data); + console.log(list); + // setList(list); + + if (data as IStateData) { + // fixed: unkonwn 类型只能分配给 unkonwn 或者 any,所以做个类型断言。 + setList([...list, data as IStateData]); + } else { + return; + } + }); + }, [list.length]); - useEffect(() => { - layoutEmitter.useSubscription((data) => { - list.push(data); - console.log(data); - console.log(list); - setList(list); - }); - }, []) - return ( - - - list length:{list.length} - { - list.map(item => {item.state}) - } - - ) + return ( + + + list length:{list.length} + { + list.map(({ state }) => ( + {state} + )) // fixed: 少了 key,顺便把 state 解构出来,写 item.state 多麻烦。 + } + + ); }; From c9f76452df2d566b4c0e518676e40ef4b6e31712 Mon Sep 17 00:00:00 2001 From: Oblivion <915019672@qq.com> Date: Wed, 29 Jul 2020 10:32:31 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fixed:=20=E6=AF=8F=E6=AC=A1=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E6=8F=90=E4=BA=A4=E4=B8=80=E4=B8=AA=20emit=EF=BC=8C?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=20subscription=EF=BC=8C=E8=BF=9B=E8=80=8C?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=20re-render=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/EventEmitterButton.tsx | 19 ++-------- src/pages/index.tsx | 54 ++++++++++++++------------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/components/EventEmitterButton.tsx b/src/components/EventEmitterButton.tsx index c1baa39..78678fa 100644 --- a/src/components/EventEmitterButton.tsx +++ b/src/components/EventEmitterButton.tsx @@ -1,26 +1,15 @@ -// import React, { useState, useEffect } from 'react'; import React, { useState } from "react"; import { layoutEmitter } from "@/utils/EventEmitter"; -interface IState { - initNumber: number; -} - -export default ({ initNumber }: IState) => { - const [state, setstate] = useState(initNumber); - - // useEffect(() => { // unfixed: 可以在这里解决,但第一次 this._subscription 未初始化,不是个对象,会报错。 - // layoutEmitter.emit({ state }); - // return () => {} - // }, [state]) +export default ({ initNumber }: { initNumber: number }) => { + const [state, setstate] = useState(initNumber); return ( { setstate(state + 1); - layoutEmitter.emit({ state }); // unfixed: 父组件订阅不到初次的状态。 可以 emit({state + 1}),但不想被骂。 + layoutEmitter.emit({ state }); }} > EventEmitter {state}{" "} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index dc5869b..a67e81c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,43 +1,45 @@ import React, { useEffect, useState } from "react"; import { layoutEmitter } from "@/utils/EventEmitter"; import EventEmitterButton from "@/components/EventEmitterButton"; - -export interface IStateData { - state: number; +interface ListItemProps { + state?: number; } - export default () => { - const [list, setList] = useState>([]); + const [list, setList] = useState(() => []); useEffect(() => { layoutEmitter.useSubscription((data) => { - // list.push(data); - - // fixed: 不能在 setState 外直接操作 state,react 数据的不可变性。 - // 直接操作 state 会导致之前的变更无效(应该是这个原因),所以 DOM 不会重新渲染。 - - console.log(data); - console.log(list); - // setList(list); - - if (data as IStateData) { - // fixed: unkonwn 类型只能分配给 unkonwn 或者 any,所以做个类型断言。 - setList([...list, data as IStateData]); - } else { - return; - } + // 按你们的写法实现的 + // bug 重现步骤 + // 点击 EventEmitterButton 两次 + // 点击 Add List 一次 + // 点击 EventEmitterButton 一次 + // 期望结果 + // 11 + // 12 + // 时间戳 + // 13 + list.push(data as ListItemProps); + setList([...list]); }); - }, [list.length]); + }, []); return ( + { + // setList([...list, { state: new Date().getTime() }]); // 不会触发 useEffect,也就不会 re-render + layoutEmitter.emit({ state: new Date().getTime() }); // fixed: 每次点击提交一个 emit,触发 subscription,进行 setList。 + }} + > + Add List + list length:{list.length} - { - list.map(({ state }) => ( - {state} - )) // fixed: 少了 key,顺便把 state 解构出来,写 item.state 多麻烦。 - } + {list.map((item) => ( + {item.state} + ))} ); };
list length:{list.length}
{item.state}
{state}