【问题标题】:React: how to replicate a specific component class setstate callback example with functional usestate/useEffect?React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?
【发布时间】: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 回调组件替换为函数组件的建议。

欢迎提出任何建议。

【问题讨论】:

    标签: reactjs callback setstate use-effect use-state


    【解决方案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 回调功能。
      猜你喜欢
      • 2021-02-28
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2020-09-10
      • 2021-11-26
      • 1970-01-01
      • 2021-04-20
      相关资源
      最近更新 更多