ReactJS生命周期方法在功能组件内部

时间:2017-06-12 18:20:04

标签: reactjs redux

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

如何覆盖功能组件中的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>  
    )
}

8 个答案:

答案 0 :(得分:49)

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

  

Hooks是一项新功能提案,可让您使用状态和其他   无需编写课程即可实现功能。它们作为 v16.8.0

的一部分在React中发布

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

您可以在像

这样的钩子中实现您的用例
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也可以返回在卸载组件时运行的函数。这可以用于取消订阅听众。 An可用于复制componentWillUnmount行为

例如:componentWillUnmount

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

作为第二个参数,如果你提供值,那么这些将在触发回调之前进行比较,如果这些是以下任何一个的任何变化

例如:componentDidUpdate

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

Hooks Equivalent

useEffect(() => {
     // action here
}, [props.counter]);

在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>  
    )
  }
}

当您只想渲染Component而不需要额外的逻辑时,功能组件非常有用。

答案 1 :(得分:43)

您可以使用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);

答案 2 :(得分:8)

您可以使用hooks来制作自己的“生命周期方法”,以最大程度地怀旧。

实用程序功能

import { useEffect, useRef } from "react";

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

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

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

      return;
    }

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

用法:

import { componentDidMount, componentDidUpdate } from "./utils";

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

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

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

答案 3 :(得分:7)

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

钩子使您无需类即可使用React的更多功能。 挂钩为您已经知道的React概念提供了更直接的API:道具,状态,上下文,引用和生命周期。 Hooks解决了Recompose解决的所有问题。

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

  

嗨!我大约在三年前创建了Recompose。大约一年后   我加入了React团队。今天,我们宣布了一项   钩子。挂钩解决了我试图解决的所有问题   三年前重新组合,最重要的是。我会   停止对此软件包的主动维护(可能不包括   与未来的React版本兼容的错误修正或补丁),以及   建议人们改用挂钩。您现有的代码与   重新组合仍然可以使用,只是不要期待任何新功能。

解决方案二:

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

这是一个无需渲染的组件,可通过生命周期HOC(通过重新组合)附加生命周期方法

// 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);

答案 4 :(得分:3)

如果您需要使用React LifeCycle,则需要使用Class。

样品:

include('/lib/Vendor/autoload.php');

use Twilio\Rest\Client;

$sid = "";
$token = "";
$client = new Client($sid,$token);

foreach ($client->incomingPhoneNumbers->read() as $number) {
    echo $number->phoneNumber;
}

答案 5 :(得分:0)

您可以使用create-react-class模块。 Official documentation

当然您必须先安装它

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')
)

答案 6 :(得分:0)

如果您使用react 16.8,则可以使用react Hooks ... React Hooks是使您能够“挂钩”功能组件中的React状态和生命周期功能的函数... docs

答案 7 :(得分:0)

根据文档:

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

useEffect(() => {


});

请参阅React documentation

相关问题