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

时间:2021-02-19 13:15:47

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

我正在尝试将带有 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 回调组件提供建议。

欢迎提出任何建议。

2 个答案:

答案 0 :(得分:0)

这里不需要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>
  );
};

答案 1 :(得分:-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()(例如 setValues 或第 7 步中的 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 步:用 useEffect 替换 componentDidUpdate 或 componentWillReceiveProps

useEffect(() => {
     console.log(myPropsToCheck+ " has changed ! ")
    }, [myPropsToCheck])
})