Phương thức vòng đời ReactJS bên trong một Thành phần hàm


135

Thay vì viết các thành phần của tôi bên trong một lớp, tôi muốn sử dụng cú pháp hàm để thay thế.

Làm thế nào để ghi đè lên componentDidMount, componentWillMountbên trong các thành phần chức năng?
Nó thậm chí có thể?

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

1
các thành phần chức năng không được cho là có các phương thức vòng đời. bởi vì chúng chỉ là các chức năng. và các hàm không có phương thức. có các lớp học cho điều đó
avalanche1

Câu trả lời:


149

Chỉnh sửa: Với việc giới thiệu Hooksnó, có thể thực hiện một loại hành vi vòng đời cũng như trạng thái trong các Thành phần chức năng. Hiện tại

Hooks là một đề xuất tính năng mới cho phép bạn sử dụng trạng thái và các tính năng khác của React mà không cần viết một lớp. Chúng được phát hành trong React như một phần của v16.8.0

useEffecthook có thể được sử dụng để tái tạo hành vi vòng đời và useStatecó thể được sử dụng để lưu trữ trạng thái trong một thành phần chức năng.

Cú pháp cơ bản:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

Bạn có thể triển khai trường hợp sử dụng của mình trong các hook như

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

useEffectcũng có thể trả về một chức năng sẽ được chạy khi thành phần được ngắt kết nối. Điều này có thể được sử dụng để hủy đăng ký cho người nghe, sao chép hành vi của componentWillUnmount:

Vd: componentWillUnmount

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

Để tạo useEffectđiều kiện cho các sự kiện cụ thể, bạn có thể cung cấp cho nó một mảng giá trị để kiểm tra các thay đổi:

Vd: componentDidUpdate

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

Móc tương đương

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

Nếu bạn bao gồm mảng này, hãy đảm bảo bao gồm tất cả các giá trị từ phạm vi thành phần thay đổi theo thời gian (đạo cụ, trạng thái) hoặc bạn có thể tham chiếu đến các giá trị từ các lần hiển thị trước đó.

Có một số tinh tế khi sử dụng useEffect; kiểm tra API Here.


Trước v16.7.0

Thuộc tính của các thành phần chức năng là chúng không có quyền truy cập vào các chức năng vòng đời của Reacts hoặc thistừ khóa. Bạn cần mở rộng React.Componentlớp nếu bạn muốn sử dụng chức năng vòng đời.

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

Các thành phần chức năng hữu ích khi bạn chỉ muốn hiển thị Thành phần của mình mà không cần thêm logic.


1
Như tôi đã nói, bạn có một logic trong thành phần của mình và yêu cầu của bạn muốn bạn sử dụng một hàm vòng đời và bạn không thể làm điều đó với các thành phần functioanl. Vì vậy, tốt hơn hãy tận dụng lớp học. Sử dụng thành phần chức năng khi thành phần của bạn không chứa thêm Logic
Shubham Khatri

1
Cần lưu ý rằng đây không phải là componentDidUpdate chính xác tương đương. useEffect(() => { // action here }, [props.counter])được kích hoạt khi hiển thị ban đầu trong khi componentDidUpdate thì không.
Estus Flask

1
passing an empty array as second argument triggers the callback in useEffect only after the initial renderđiều này nghe có vẻ giống như một cách xây dựng nội dung theo kiểu hacky bẩn thỉu: / hy vọng nhóm phản ứng sẽ đưa ra thứ gì đó tốt hơn trong các bản phát hành trong tương lai.
Lukas Liesis

3
vì thế? phần mà bạn trả lời cách chạy mã trên componentwillmount ở đâu?
Toskan

59

Bạn có thể sử dụng vòng đời phản ứng thuần túy để thêm các chức năng vòng đời vào các thành phần chức năng.

Thí dụ:

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

3
Gridgì? Tôi không thấy nó được định nghĩa ở bất kỳ đâu trong đoạn mã của bạn? Nếu bạn cũng muốn sử dụng redux với cái này, bạn có thể sử dụng cái gì đó như thế export default lifecycle(methods)(connect({},{})(ComponentName))nào không?
Sean Clancy

@SeanClancy Xin lỗi vì phản hồi muộn. Đoạn mã đã được cập nhật.
Yohann

1
Đây có phải là một thực hành tốt? Tôi có nên thử các giải pháp khác nhau trước khi đạt được giải pháp này không hay có thể sử dụng nó nếu tôi thấy dễ nhất không?
SuperSimplePimpleDimple

9

Giải pháp một: Bạn có thể sử dụng API HOOKS phản ứng mới . Hiện đang có trong React v16.8.0

Hooks cho phép bạn sử dụng nhiều tính năng của React hơn mà không cần lớp. Hooks cung cấp một API trực tiếp hơn cho các khái niệm React mà bạn đã biết: đạo cụ, trạng thái, ngữ cảnh, giới thiệu và vòng đời . Hooks giải quyết tất cả các vấn đề được giải quyết với Recompose.

Lưu ý từ Tác giả của recompose(acdlite, ngày 25 tháng 10 năm 2018):

Chào! Tôi đã tạo Recompose khoảng ba năm trước. Khoảng một năm sau đó, tôi gia nhập nhóm React. Hôm nay, chúng tôi đã công bố một đề xuất cho Hooks. Hooks giải quyết tất cả các vấn đề mà tôi đã cố gắng giải quyết với Recompose ba năm trước, và hơn thế nữa. Tôi sẽ ngừng bảo trì tích cực gói này (có lẽ không bao gồm các bản sửa lỗi hoặc bản vá để tương thích với các bản phát hành React trong tương lai) và khuyên mọi người nên sử dụng Hooks thay thế. Mã hiện có của bạn với Recompose sẽ vẫn hoạt động, chỉ cần bạn không mong đợi bất kỳ tính năng mới nào.

Giải pháp thứ hai:

Nếu bạn đang sử dụng phiên bản react không hỗ trợ hook, đừng lo lắng, hãy sử dụng recompose(Một vành đai tiện ích React cho các thành phần chức năng và các thành phần bậc cao hơn.). Bạn có thể sử dụng recomposeđể gắn lifecycle hooks, state, handlers etcvào một thành phần chức năng.

Đây là một thành phần ít kết xuất gắn các phương thức vòng đời qua HOC vòng đời (từ biên soạn lại).

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

Bạn có thể thực hiện các phương pháp vòng đời của riêng bạn.

Các chức năng tiện ích

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

Sử dụng

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]);
};  

2

Theo tài liệu:

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

useEffect(() => {


});

xem tài liệu React


0

Nếu bạn cần sử dụng React LifeCycle, bạn cần sử dụng Class.

Mẫu vật:

import React, { Component } from 'react';

class Grid extends Component {

 constructor(props){
  super(props)
 }

 componentDidMount () { /* do something */ }

 render () { 
   return <h1>Hello</h1>
 }

}

2
Tôi không muốn sử dụng lớp học.
Aftab Naveed

3
Câu hỏi là làm thế nào để sử dụng các phương thức vòng đời với một thành phần chức năng, không phải một lớp.
Mike

Bây giờ, với Phản ứng Móc
Gabriel Ferreira

0

Bạn có thể sử dụng mô-đun lớp tạo-phản ứng. Tài liệu chính thức

Tất nhiên trước tiên bạn phải cài đặt nó

npm install create-react-class

Đây là một ví dụ hoạt động

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

0

nếu bạn sử dụng react 16.8, bạn có thể sử dụng react Hooks ... React Hooks là các hàm cho phép bạn "nhập vào" trạng thái React và các tính năng vòng đời từ các thành phần hàm ... tài liệu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.