React:如何使用功能 usestate/useEffect 复制特定组件 class setstate 回调示例?

React: how to replicate a specific component class setstate callback example with functional usestate/useEffect?

我正在尝试将带有 this.setstate 回调的简单 React 组件转换为带有 useState/useEffect 的功能组件,但我无法使用后者重现相同的功能。

我正在使用一个简单的 alert/notice 系统示例来在超时后添加和删除警报。这里的沙盒:

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.

功能组件替换正常运行的 class 组件 setstate 回调组件提出建议

欢迎提出任何建议。

从 class 到功能组件需要一些步骤:

步骤 1 :

class NameOfComponent extends Component

变成

function NameOfComponent(props){

步骤 2:删除 constructor

步骤 3:删除 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 步:- 通过您定义的 setter 更改 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])
})

这里不需要useEffect。每次更改 alerts 数组时都会触发 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>
  );
};