React Lifecycle & useEffect: Class Methods vs Modern Hooks ??

React Lifecycle & useEffect: Class Methods vs Modern Hooks ??

Ever wondered how React components "live and breathe"? Let's dive into component lifecycles and see how modern hooks have revolutionized the way we handle component life events!


The Big Picture: Class Lifecycle vs useEffect ??

Traditional Class Lifecycle

class DataFetcher extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null }; // Setup
  }

  componentDidMount() {
    // When component is born
    this.fetchData();
  }

  componentDidUpdate(prevProps) {
    // When component updates
    if (prevProps.id !== this.props.id) {
      this.fetchData();
    }
  }

  componentWillUnmount() {
    // Cleanup when component dies
    this.ignore = true;
  }

  fetchData = async () => {
    const result = await fetch(`/api/data/${this.props.id}`);
    const data = await result.json();
    if (!this.ignore) {
      this.setState({ data });
    }
  };

  render() {
    return <div>{/* Render data */}</div>;
  }
}        


Modern Hooks Approach

function DataFetcher({ id }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    let ignore = false;

    async function fetchData() {
      const result = await fetch(`/api/data/${id}`);
      const data = await result.json();
      if (!ignore) {
        setData(data);
      }
    }

    fetchData();
    return () => {
      ignore = true; // Cleanup
    };
  }, [id]); // Dependencies

  return <div>{/* Render data */}</div>;
}        


Lifecycle Methods vs useEffect: Side-by-Side ??

1. Component Mounting

// Class Method
componentDidMount() {
  console.log('Component born');
  document.title = this.props.title;
}

// Hook Equivalent
useEffect(() => {
  console.log('Component born');
  document.title = title;
}, []); // Empty dependency array = componentDidMount        

2. Component Updating

// Class Method
componentDidUpdate(prevProps) {
  if (prevProps.title !== this.props.title) {
    document.title = this.props.title;
  }
}

// Hook Equivalent
useEffect(() => {
  document.title = title;
}, [title]); // Runs when title changes        

3. Component Cleanup

// Class Method
componentWillUnmount() {
  window.removeEventListener('resize', this.handleResize);
}

// Hook Equivalent
useEffect(() => {
  window.addEventListener('resize', handleResize);
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, []); // Cleanup function in return        

Real-World Examples ??

1. WebSocket Connection

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket(`ws://chat.api/${roomId}`);
    
    socket.onmessage = (event) => {
      setMessages(prev => [...prev, event.data]);
    };

    return () => socket.close(); // Cleanup on unmount or roomId change
  }, [roomId]);

  return <div>{/* Render messages */}</div>;
}        

2. Subscription Management

function UserStatus({ userId }) {
  const [isOnline, setIsOnline] = useState(false);

  useEffect(() => {
    const subscription = subscribeToUserStatus(userId, status => {
      setIsOnline(status.online);
    });

    // Cleanup subscription
    return () => subscription.unsubscribe();
  }, [userId]); // Resubscribe when userId changes

  return <div>User is: {isOnline ? '??' : '?'}</div>;
}        

3. Animation Controller

function AnimatedComponent({ isVisible }) {
  const elementRef = useRef(null);

  useEffect(() => {
    if (!elementRef.current) return;

    const animation = elementRef.current.animate([
      { opacity: 0 },
      { opacity: 1 }
    ], {
      duration: 1000,
      fill: 'forwards'
    });

    return () => animation.cancel(); // Cleanup animation
  }, [isVisible]);

  return <div ref={elementRef}>{/* Content */}</div>;
}        

Common useEffect Patterns ??

  1. Data Fetching

useEffect(() => {
  let mounted = true;

  async function loadData() {
    const data = await fetchData();
    if (mounted) {
      setData(data);
    }
  }

  loadData();
  return () => {
    mounted = false;
  };
}, [/* dependencies */]);        

2. Event Listeners

useEffect(() => {
  const handler = (event) => {
    // Handle event
  };

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

3. Intervals/Timers

useEffect(() => {
  const interval = setInterval(() => {
    // Do something
  }, 1000);

  return () => clearInterval(interval);
}, []);        

Best Practices ??

  1. Always clean up side effects
  2. Use multiple useEffects for different concerns
  3. Keep dependency arrays accurate
  4. Avoid infinite loops
  5. Use cleanup functions when needed

?? Weekly Challenge

Convert this class component to use hooks:

class ScrollTracker extends React.Component {
  state = { scrollY: 0 };

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = () => {
    this.setState({ scrollY: window.scrollY });
  };

  render() {
    return <div>Scrolled: {this.state.scrollY}px</div>;
  }
}        



要查看或添加评论,请登录

Dhruv Patel的更多文章

社区洞察

其他会员也浏览了