React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?
Posted
技术标签:
【中文标题】React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?【英文标题】:React: how to replicate a specific component class setstate callback example with functional usestate/useEffect? 【发布时间】:2021-05-22 11:39:14 【问题描述】:我正在尝试将带有 this.setstate 回调的简单 React 组件转换为带有 useState/useEffect 的功能组件,但我无法使用后者重现相同的功能。
我正在使用一个简单的警报/通知系统示例来在超时后附加和删除警报。沙盒在这里:
https://codesandbox.io/s/class-and-function-callback-comparison-54tus?file=/src/index.js
相关代码对比:
const NoticesWithFunctionCallback = () =>
const [state, setState] = useState(
alerts: [],
show: false
);
const addNotice = (e) =>
setState(
alerts: [...state.alerts, ""]
);
;
useEffect(() =>
(async () =>
await timeout(3000);
console.log("timeout occurred");
const newAlerts = tail([...state.alerts]);
setState(
alerts: newAlerts
);
)();
, [state.alerts]);
return (
<div className="App">
<h3>
Notices using function component with UseState and UseEffect callback
</h3>
<Generator addNotice=addNotice />
<Container>
state.alerts.map((item, index) => (
<Alert>some alert here</Alert>
))
</Container>
</div>
);
;
class NoticesWithClassCallback extends React.Component
state =
alerts: [],
show: false
;
addNotice = (e) =>
this.setState(
alerts: [...this.state.alerts, ""]
,
async () =>
await timeout(3000);
console.log("timeout occurred");
const newAlerts = tail([...this.state.alerts]);
this.setState(
alerts: newAlerts
);
);
;
render()
return (
<div className="App">
<h3>Notices using class component and setState callback</h3>
<Generator addNotice=this.addNotice />
<Container>
this.state.alerts.map((item, index) => (
<Alert>some alert here</Alert>
))
</Container>
</div>
);
我希望关于如何使用 usestate/useeffect 将功能正确的类组件 setstate 回调组件替换为函数组件的建议。
欢迎提出任何建议。
【问题讨论】:
【参考方案1】:这里不需要useEffect。每次更改警报数组时都会触发 useEffect :通过向其中添加项目以及删除。它也在初始化后立即触发,所以事情变得一团糟。相反,您应该修改 addNotice 函数并使用之前的函数更新状态,如下所示:
const NoticesWithFunctionCallback = () =>
const [state, setState] = useState(
alerts: [],
show: false
);
const addNotice = (e) =>
setState(
...state,
alerts: [...state.alerts, '']
);
(async () =>
await timeout(3000);
setState(prevState =>
return
...prevState,
alerts: [...tail([...prevState.alerts])]
);
)()
;
return (
<div className="App">
<h3>
Notices using function component with UseState and UseEffect callback
</h3>
<p>I want this to replicate the class component but its broken...</p>
<Generator addNotice=addNotice />
<Container>
state.alerts.map((item, index) => (
<Alert key=index>Alert</Alert>
))
</Container>
</div>
);
;
【讨论】:
【参考方案2】:从一个类到一个功能组件有一些步骤:
第 1 步:
class NameOfComponent extends Component
变成
function NameOfComponent(props)
第 2 步:删除constructor
第三步:去掉render()
方法,保留return
第 4 步。在所有方法之前添加const
第 5 步:在整个组件中删除 this.state
第 6 步。删除整个组件中对“this”的所有引用
第 7 步:使用useState()
设置初始状态(并从“react”导入)
数字示例:
const [count, setCount] = useState(0) // the useState() param is the initial value
对象示例:
const [form, setValues] = useState(
id: 0,
first: ‘’,
last: ‘’,
password: ‘’,
subscribe: false
)
第 8 步: - 将 this.setState()
更改为您定义的设置器(例如第 7 步中的 setValues 或 setCount)
this.setState( count: this.state.count + 1 )
将变为 setCount(count+1)
第 9 步: 将 componentDidMount
替换为 useEffect
useEffect(() =>
fetch(‘url’)
.then(res => res.json())
.then(items => setSomething(items)
.catch(console.log(err))
, [])
第 10 步: 将 componentDidUpdate 或 componentWillReceiveProps 替换为 useEffect
useEffect(() =>
console.log(myPropsToCheck+ " has changed ! ")
, [myPropsToCheck])
)
【讨论】:
谢谢,但问题与如何将类组件转换为功能组件无关,因为这已经完成,而是具体如何重现此特定示例的 setstate 回调功能。以上是关于React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?的主要内容,如果未能解决你的问题,请参考以下文章
React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?
如何防止我的功能组件使用 React 备忘录或 React 钩子重新渲染?
如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?