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 备忘录或 React 钩子重新渲染?

如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?

如何使用 React-Hooks 和 Apollo Client 在 React-GraphQL 中实现搜索功能?

如何使用 Jest/Enzyme 在功能性 React 组件中测试 lambda 函数?