簡體   English   中英

將基於 Class 的組件轉換為基於功能的組件

[英]transform Class based component to functional based component

伙計們,我想轉換這段代碼:

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = { isLoading: true };
  }

  performTimeConsumingTask = async () => {
    return new Promise((resolve) =>
      setTimeout(() => {
        resolve('result');
      }, 2000)
    );
  };

  async componentDidMount() {
    const data = await this.performTimeConsumingTask();
    if (data !== null) this.setState({ isLoading: false });
  }

  render() {

    if (this.state.isLoading) return <SplashScreen />;

    const { state, navigate } = this.props.navigation;

    return (something)

我寫了這段代碼,但它不起作用:

const App = () => {
  const [fontLoaded, setFontLoaded] = useState(false);
  const [isTimerOn, setIsTimerOn] = useState(true);

  if (!fontLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onFinish={() => setFontLoaded(true)}
      />
    );
  }
  useEffect(async () => {
    const data = await performTimeConsumingTask();
    if (data !== null) setIsTimerOn(false);
  });
  if (isTimerOn) return <SplashScreen />;
  else {
    return (something)

這將顯示一個錯誤: Invariant Violation: Rendered More Hooks than during the previous render.

如果我評論useEffect鈎子,它將運行splashScreen 任何人都可以幫我轉換它嗎?

在使用所有鈎子之前必須沒有條件返回,在您的情況下,您在使用之前返回useEffect

此外useEffect不得在每個渲染上運行,因為它在您的情況下設置了 state。 由於您只希望它在初始渲染時運行,因此將一個空數組作為第二個參數傳遞。

另外useEffect回調function不能是異步的。

在文檔中閱讀有關useEffect掛鈎的更多信息。

檢查下面的更新代碼

const App = () => {
  const [fontLoaded, setFontLoaded] = useState(false);
  const [isTimerOn, setIsTimerOn] = useState(true);

  const performTimeConsumingTask = async () => {
      return new Promise((resolve) =>
         setTimeout(() => {
           resolve('result');
        }, 2000)
   );
  };
  useEffect(() => {
    async function myFunction() {
       const data = await performTimeConsumingTask();
       if (data !== null) setIsTimerOn(false);
    }
    myFunction();
  }, []); // With empty dependency it runs on initial render only like componentDidMount

  if (!fontLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onFinish={() => setFontLoaded(true)}
      />
    );
  }
  if (isTimerOn) return <SplashScreen />;
  else {
    return (something)

如果您想將此鈎子用作componentDidMount ,請將[]作為參數傳遞

useEffect(async () => {
const data = await performTimeConsumingTask();
if (data !== null) setIsTimerOn(false);
}, []); 

這是一個鈎子列表,您可以如何使用鈎子來替換生命周期方法

https://medium.com/javascript-in-plain-english/lifecycle-methods-substitute-with-react-hooks-b173073052a

出現錯誤的原因是您的組件渲染次數過多,並且useEffect也在每個渲染上運行,通過傳遞[]將在第一次渲染時運行useEffect ,因為它的行為類似於 componentDidMount。

也可以按照這個在useEffect中進行網絡調用

https://medium.com/javascript-in-plain-english/handling-api-calls-using-async-await-in-useeffect-hook-990fb4ae423

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM