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

Aft*_*eed 74 reactjs redux

而不是在类中编写我的组件,因为它们是愚蠢的,我主要在函数内写这些.

但我怎么覆盖componentDidMount,componentWillMount内部的功能部件?它甚至可能吗?

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>  
    )
}
Run Code Online (Sandbox Code Playgroud)

Shu*_*tri 84

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

Hook是一项新功能提案,可让您在不编写类的情况下使用状态和其他React功能.它们作为v16.8.0的一部分在React中发布

useEffecthook可用于复制生命周期行为,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>  
    )
}
Run Code Online (Sandbox Code Playgroud)

useEffect还可以返回卸载组件时将运行的函数.这可以用于取消订阅听众.An可用于复制componentWillUnmount行为

例如:componentWillUnmount

useEffect(() => {
    window.addEventListener('unhandledRejection', handler);
    return () => {
       window.removeEventListener('unhandledRejection', handler);
    }
}, [])
Run Code Online (Sandbox Code Playgroud)

作为第二个参数,如果您提供值,则在触发回调之前将对这些值进行比较,如果这些是以下任何一项中的任何更改

例如:componentDidUpdate

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

钩子相当于

useEffect(() => {
     // action here
}, [props.counter]);
Run Code Online (Sandbox Code Playgroud)

在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>  
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 所以?您回答如何在 componentwillmount 上运行代码的部分在哪里? (6认同)
  • `传递一个空数组作为第二个参数只会在初始渲染后触发 useEffect 中的回调`这听起来像是一种肮脏的 hacky 构建方式:/希望 React 团队会在未来的版本中提出更好的东西。 (3认同)
  • 应该注意的是,这并不完全等同于 componentDidUpdate。`useEffect(() =&gt; { // 这里的操作 }, [props.counter])` 在初始渲染时触发,而 componentDidUpdate 则不会。 (2认同)

Yoh*_*ann 56

您可以使用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);
Run Code Online (Sandbox Code Playgroud)

  • 什么是'网格'?我没有看到它在您的代码段中的任何位置定义?如果你想使用redux,你也可以使用`export default lifecycle(methods)(connect({},{})(ComponentName))` (3认同)

Eti*_*tin 16

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

实用功能:

import { useEffect, useRef } from "react";

export const useComponentDidMount = handler => {
  return useEffect(() => {
    return 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, []);
};

Run Code Online (Sandbox Code Playgroud)

用法:

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!");
  });
};  
Run Code Online (Sandbox Code Playgroud)


Shi*_*vam 8

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

Hooks让你可以在没有类的情况下使用更多React的功能. Hook为您已经知道的React概念提供了更直接的API:props,state,context,refs和lifecycle.Hooks解决了Recompose解决的所有问题.

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

嗨!我大约三年前创建了Recompose.大约一年后,我加入了React团队.今天,我们宣布了针对Hooks的提案.Hooks解决了我三年前尝试用Recompose解决的所有问题,并且更多地解决了这个问题.我将停止对此软件包的主动维护(可能不包括错误修正或补丁以便与未来的React版本兼容),并建议人们使用Hooks代替.使用Recompose的现有代码仍然有效,只是不要指望任何新功能.

解决方案二:

如果您使用不支持挂钩的反应版本,请不要担心,请使用recompose(功能组件的反射实用程序带和更高阶的组件.).您可以使用recompose附加lifecycle 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);
Run Code Online (Sandbox Code Playgroud)


小智 8

组件已挂载

useEffect(()=>{
   // code here
})
Run Code Online (Sandbox Code Playgroud)

组件将挂载

useEffect(()=>{

   return ()=>{ 
                //code here
              }
})
Run Code Online (Sandbox Code Playgroud)

组件更新

useEffect(()=>{

    //code here
    // when userName state change it will call     
},[userName])
Run Code Online (Sandbox Code Playgroud)

  • @Somitya - 您是否应该写“componentWillUnmount”而不是“componentWillMount”? (2认同)