繁体   English   中英

函数组件内的 ReactJS 生命周期方法

[英]ReactJS lifecycle method inside a function Component

我不想在类中编写组件,而是使用函数语法。

如何在函数组件中覆盖componentDidMountcomponentWillMount
甚至可能吗?

const grid = (props) => {
    console.log(props);
    let {skuRules} = props;

    const componentDidMount = () => {
        if(!props.fetched) {
            props.fetchRules();
        }
        console.log('mount it!');
    };
    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
}

编辑:随着Hooks的引入,可以实现生命周期类型的行为以及功能组件中的状态。 目前

Hooks 是一个新的特性提议,它允许你在不编写类的情况下使用状态和其他 React 特性。 它们作为v16.8.0的一部分在 React 中发布

useEffect hook 可用于复制生命周期行为,而useState可用于将状态存储在功能组件中。

基本语法:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

您可以在钩子中实现您的用例,例如

const grid = (props) => {
    console.log(props);
    let {skuRules} = props;

    useEffect(() => {
        if(!props.fetched) {
            props.fetchRules();
        }
        console.log('mount it!');
    }, []); // passing an empty array as second argument triggers the callback in useEffect only after the initial render thus replicating `componentDidMount` lifecycle behaviour

    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
}

useEffect还可以返回一个函数,该函数将在卸载组件时运行。 这可用于取消订阅侦听器,复制componentWillUnmount的行为:

例如:componentWillUnmount

useEffect(() => {
    window.addEventListener('unhandledRejection', handler);
    return () => {
       window.removeEventListener('unhandledRejection', handler);
    }
}, [])

要使useEffect以特定事件为条件,您可以为其提供一组值以检查更改:

例如:componentDidUpdate

componentDidUpdate(prevProps, prevState) {
     const { counter } = this.props;
     if (this.props.counter !== prevState.counter) {
      // some action here
     }
}

挂钩等效

useEffect(() => {
     // action here
}, [props.counter]); // checks for changes in the values in this array

如果包含此数组,请确保包含组件范围内随时间变化的所有值(道具、状态),否则您最终可能会引用先前渲染中的值。

使用useEffect有一些微妙之处; Here查看 API。


v16.7.0之前

函数组件的属性是它们无法访问 Reacts 生命周期函数或this关键字。 如果要使用生命周期功能,则需要扩展React.Component类。

class Grid extends React.Component  {
    constructor(props) {
       super(props)
    }

    componentDidMount () {
        if(!this.props.fetched) {
            this.props.fetchRules();
        }
        console.log('mount it!');
    }
    render() {
    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
  }
}

当您只想渲染组件而不需要额外的逻辑时,函数组件很有用。

您可以使用react-pure-lifecycle为功能组件添加生命周期功能。

例子:

import React, { Component } from 'react';
import lifecycle from 'react-pure-lifecycle';

const methods = {
  componentDidMount(props) {
    console.log('I mounted! Here are my props: ', props);
  }
};

const Channels = props => (
<h1>Hello</h1>
)

export default lifecycle(methods)(Channels);

您可以使用钩子制作自己的“生命周期方法”,以获得最大的怀旧感。

实用功能:

import { useEffect, useRef } from "react";

export const useComponentDidMount = handler => {
  return useEffect(() => handler(), []);
};

export const useComponentDidUpdate = (handler, deps) => {
  const isInitialMount = useRef(true);

  useEffect(() => {
    if (isInitialMount.current) {
      isInitialMount.current = false;

      return;
    }

    return handler();
  }, deps);
};

export const useComponentWillUnmount = handler => {
  return useEffect(() => handler, []);
};

用法:

import {
  useComponentDidMount,
  useComponentDidUpdate,
  useComponentWillUnmount
} from "./utils";

export const MyComponent = ({ myProp }) => {
  useComponentDidMount(() => {
    console.log("Component did mount!");
  });

  useComponentDidUpdate(() => {
    console.log("Component did update!");
  });

  useComponentDidUpdate(() => {
    console.log("myProp did update!");
  }, [myProp]);

  useComponentWillUnmount(() => {
    console.log("Component will unmount!");
  });

  return <div>Hello world</div>;
};  

解决方案一:您可以使用新的 react HOOKS API。 目前在React v16.8.0

Hooks 让你可以在没有类的情况下使用更多 React 的特性。 Hooks 为你已经知道的 React 概念提供了更直接的 API:props、state、context、refs 和生命周期 Hooks 解决了 Recompose 解决的所有问题。

recompose作者的注释(acdlite,2018 年 10 月 25 日):

你好! 大约三年前,我创建了 Recompose。 大约一年后,我加入了 React 团队。 今天,我们宣布了 Hooks 的提案。 Hooks 解决了我三年前尝试使用 Recompose 解决的所有问题,除此之外还有更多问题。 我将停止对该包的积极维护(可能不包括错误修复或与未来 React 版本兼容的补丁),并建议人们改用 Hooks。 您使用 Recompose 的现有代码仍然可以工作,只是不要期望任何新功能。

解决方案二:

如果您使用的是不支持 hooks 的 react 版本,不用担心,请使用recompose (用于功能组件和高阶组件的 React 实用工具带。)。 您可以使用recomposelifecycle hooks, state, handlers etc附加到功能组件。

这是一个无渲染组件,它通过生命周期 HOC(来自 recompose)附加生命周期方法

// taken from https://gist.github.com/tsnieman/056af4bb9e87748c514d#file-auth-js-L33

function RenderlessComponent() {
  return null; 
}

export default lifecycle({

  componentDidMount() {
    const { checkIfAuthed } = this.props;
    // Do they have an active session? ("Remember me")
    checkIfAuthed();
  },

  componentWillReceiveProps(nextProps) {
    const {
      loadUser,
    } = this.props;

    // Various 'indicators'..
    const becameAuthed = (!(this.props.auth) && nextProps.auth);
    const isCurrentUser = (this.props.currentUser !== null);

    if (becameAuthed) {
      loadUser(nextProps.auth.uid);
    }

    const shouldSetCurrentUser = (!isCurrentUser && nextProps.auth);
    if (shouldSetCurrentUser) {
      const currentUser = nextProps.users[nextProps.auth.uid];
      if (currentUser) {
        this.props.setCurrentUser({
          'id': nextProps.auth.uid,
          ...currentUser,
        });
      }
    }
  }
})(RenderlessComponent);

组件DidMount

useEffect(()=>{
   // code here
})

组件WillMount

useEffect(()=>{

   return ()=>{ 
                //code here
              }
})

组件DidUpdate

useEffect(()=>{

    //code here
    // when userName state change it will call     
},[userName])

简短而甜蜜的答案

组件DidMount

useEffect(()=>{
   // code here
})

组件WillUnmount

useEffect(()=>{

   return ()=>{ 
                //code here
              }
})

组件DidUpdate

useEffect(()=>{

    //code here
    // when userName state change it will call     
},[userName])

根据文档:

import React, { useState, useEffect } from 'react'
// Similar to componentDidMount and componentDidUpdate:

useEffect(() => {


});

参见反应文档

您可以使用 create-react-class 模块。 官方文档

当然你必须先安装它

npm install create-react-class

这是一个工作示例

import React from "react";
import ReactDOM from "react-dom"
let createReactClass = require('create-react-class')


let Clock = createReactClass({
    getInitialState:function(){
        return {date:new Date()}
    },

    render:function(){
        return (
            <h1>{this.state.date.toLocaleTimeString()}</h1>
        )
    },

    componentDidMount:function(){
        this.timerId = setInterval(()=>this.setState({date:new Date()}),1000)
    },

    componentWillUnmount:function(){
        clearInterval(this.timerId)
    }

})

ReactDOM.render(
    <Clock/>,
    document.getElementById('root')
)

如果你使用 react 16.8,你可以使用 react Hooks ... React Hooks 是让你从函数组件“挂钩” React 状态和生命周期特性的函数...... docs

import React, { useState, useEffect } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  // componentDidMount
  useEffect(() => {
    console.log("The use effect ran");
  }, []);

  // // componentDidUpdate
  useEffect(() => {
    console.log("The use effect ran");
  }, [count, count2]);

  // componentWillUnmount
  useEffect(() => {
    console.log("The use effect ran");
    return () => {
      console.log("the return is being ran");
    };
  }, []);

  useEffect(() => {
    console.log(`The count has updated to ${count}`);
    return () => {
      console.log(`we are in the cleanup - the count is ${count}`);
    };
  }, [count]);

  return (
    <div>
      <h6> Counter </h6>
      <p> current count: {count} </p>
      <button onClick={() => setCount(count + 1)}>increment the count</button>
      <button onClick={() => setCount2(count2 + 1)}>increment count 2</button>
    </div>
  );
};

export default Counter;

与其将我的组件写在一个类中,我想使用函数语法。

如何重写componentDidMountcomponentWillMount内部功能部件?
可能吗?

const grid = (props) => {
    console.log(props);
    let {skuRules} = props;

    const componentDidMount = () => {
        if(!props.fetched) {
            props.fetchRules();
        }
        console.log('mount it!');
    };
    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM