अद्यतन प्रतिक्रिया घटक हर सेकंड


114

मैं रिएक्ट के साथ खेल रहा हूं और निम्नलिखित समय घटक है जो सिर्फ Date.now()स्क्रीन पर प्रस्तुत करता है:

import React, { Component } from 'react';

class TimeComponent extends Component {
  constructor(props){
    super(props);
    this.state = { time: Date.now() };
  }
  render(){
    return(
      <div> { this.state.time } </div>
    );
  }
  componentDidMount() {
    console.log("TimeComponent Mounted...")
  }
}

export default TimeComponent;

रिएक्ट के नजरिए से समय को फिर से ड्रा करने के लिए हर सेकंड अपडेट करने के लिए इस घटक को प्राप्त करने का सबसे अच्छा तरीका क्या होगा?

जवाबों:


152

आपको setIntervalपरिवर्तन को ट्रिगर करने के लिए उपयोग करने की आवश्यकता है , लेकिन आपको टाइमर को खाली करने की भी आवश्यकता है जब घटक त्रुटियों और लीक को रोकने के लिए अनमाउंट करता है:

componentDidMount() {
  this.interval = setInterval(() => this.setState({ time: Date.now() }), 1000);
}
componentWillUnmount() {
  clearInterval(this.interval);
}

2
यदि आप एक पुस्तकालय चाहते हैं जो इस तरह की चीज को react-interval-rerender
एंडी

मैंने अपने कंस्ट्रक्टर में अपना सेटइंटरवल तरीका जोड़ा और इसने बेहतर काम किया।
अक्तीफां

89

निम्न कोड React.js वेबसाइट से एक संशोधित उदाहरण है।

मूल कोड यहां उपलब्ध है: https://reactjs.org/#a-simple-component

class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      seconds: parseInt(props.startTimeInSeconds, 10) || 0
    };
  }

  tick() {
    this.setState(state => ({
      seconds: state.seconds + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  formatTime(secs) {
    let hours   = Math.floor(secs / 3600);
    let minutes = Math.floor(secs / 60) % 60;
    let seconds = secs % 60;
    return [hours, minutes, seconds]
        .map(v => ('' + v).padStart(2, '0'))
        .filter((v,i) => v !== '00' || i > 0)
        .join(':');
  }

  render() {
    return (
      <div>
        Timer: {this.formatTime(this.state.seconds)}
      </div>
    );
  }
}

ReactDOM.render(
  <Timer startTimeInSeconds="300" />,
  document.getElementById('timer-example')
);

1
मैं किसी कारण के लिए इसे प्राप्त करते हैं। इस दृष्टिकोण का उपयोग करते समय एक। त्रुटि होती है। setInterval कॉलबैक ठीक से इस घटक के लिए बाध्य है।
बाल्ड्र्स

16
मेरे जैसे बेवकूफों के लिए: टाइमर का नाम नहीं updaterहै, क्योंकि यह अद्यतन चक्र खंडहर
baldrs

3
ईएस 6 के साथ मुझे इस तरह की एक लाइन बदलने की जरूरत है।
कपिल

क्या आप url का लिंक जोड़ सकते हैं जो संदर्भ देता है? धन्यवाद ~
फ्रेडरज

मैंने अधिक मजबूती के लिए एक प्रारूपण विधि और एक "कंस्ट्रक्टर" संपत्ति को जोड़ा।
श्री पॉलीविरल

15

@Waisky ने सुझाव दिया:

आपको setIntervalपरिवर्तन को ट्रिगर करने के लिए उपयोग करने की आवश्यकता है , लेकिन आपको टाइमर को खाली करने की भी आवश्यकता है जब घटक त्रुटियों और लीक को रोकने के लिए अनमाउंट करता है:

यदि आप हुक का उपयोग करके समान कार्य करना चाहते हैं:

const [time, setTime] = useState(Date.now());

useEffect(() => {
  const interval = setInterval(() => setTime(Date.now()), 1000);
  return () => {
    clearInterval(interval);
  };
}, []);

टिप्पणियों के बारे में:

आपको अंदर कुछ भी पास करने की आवश्यकता नहीं है []। यदि आप timeकोष्ठक में पास होते हैं, तो इसका मतलब है कि हर बार timeपरिवर्तनों के मूल्य पर प्रभाव को चलाएं , अर्थात, यह setIntervalहर बार एक नया timeपरिवर्तन करता है, बदलता है, जो कि हम नहीं देख रहे हैं। हम केवल setIntervalएक बार जब घटक माउंट हो जाता है और फिर हर 1000 सेकंड setIntervalकॉल करना चाहते हैं setTime(Date.now())। अंत में, हम clearIntervalघटक के अनमाउंट होने पर आह्वान करते हैं।

ध्यान दें कि timeहर बार timeपरिवर्तनों के मूल्य के आधार पर यह घटक अपडेट हो जाता है । यही कारण है कि डालने के साथ कोई संबंध नहीं है timeमें []की useEffect


1
आपने []दूसरे तर्क के रूप में एक खाली सरणी ( ) क्यों पास की useEffect?
मेकेर मेलिएर

प्रतिक्रिया प्रभाव हुक पर प्रलेखन हमें बताता है: "यदि आप एक प्रभाव चलाने के लिए और केवल एक बार इसे स्वच्छ करें (माउंट और अनमाउंट पर) करने के लिए, आप एक खाली सरणी ([]) एक दूसरे तर्क के रूप में पारित कर सकते हैं चाहते हैं।" लेकिन ओपी चाहता है कि प्रभाव हर दूसरे को चलाए, यानी दोबारा, यानी सिर्फ एक बार नहीं।
मेकेर मेलिएर

जो अंतर मैंने देखा अगर आप सरणी में [समय] से गुजरते हैं, तो यह हर अंतराल को घटक बना देगा और नष्ट कर देगा। यदि आप खाली सरणी [] को पास करते हैं, तो यह घटक को ताज़ा रखेगा और पृष्ठ छोड़ने पर इसे केवल अनमाउंट करें। लेकिन, किसी भी मामले में, इसे काम करने के लिए, मुझे वास्तव में रेंडर करने के लिए कुंजी = {समय} या कुंजी = {Date.now ()} जोड़ना पड़ा।
तेबू

8

घटक के componentDidMountजीवन चक्र विधि में, आप एक फ़ंक्शन को कॉल करने के लिए एक अंतराल सेट कर सकते हैं जो राज्य को अपडेट करता है।

 componentDidMount() {
      setInterval(() => this.setState({ time: Date.now()}), 1000)
 }

4
सही, लेकिन जैसा कि शीर्ष उत्तर बताता है, स्मृति रिसाव से बचने के लिए समय साफ़ करने के लिए याद रखें: घटकवल्लुमाउंट () {clearInterval (this.interval); }
अलेक्जेंडर फॉक

3
class ShowDateTime extends React.Component {
   constructor() {
      super();
      this.state = {
        curTime : null
      }
    }
    componentDidMount() {
      setInterval( () => {
        this.setState({
          curTime : new Date().toLocaleString()
        })
      },1000)
    }
   render() {
        return(
          <div>
            <h2>{this.state.curTime}</h2>
          </div>
        );
      }
    }

0

तो आप सही रास्ते पर थे। आपके अंदर componentDidMount()आप setInterval()बदलाव को ट्रिगर करने के लिए कार्य को पूरा कर सकते थे , लेकिन याद रखें कि एक घटक स्थिति को अपडेट करने का तरीका है setState(), जिससे आपके अंदर componentDidMount()यह हो सकता है:

componentDidMount() {
  setInterval(() => {
   this.setState({time: Date.now()})    
  }, 1000)
}

इसके अलावा, आप Date.now()उस कार्य का उपयोग करते हैं, जो componentDidMount()मैंने ऊपर दिए गए कार्यान्वयन के साथ किया है, लेकिन आपको यह अपडेट करने के लिए लंबे संख्या में गंदे नंबर मिलेंगे, जो मानव पठनीय नहीं है, लेकिन तकनीकी रूप से यह समय 1 जनवरी, 1970 से मिलीसेकंड में हर सेकंड को अपडेट करने का है, लेकिन हम तो सीखने और लागू करने के अलावा इस बार हम कैसे पढ़ा समय मनुष्य के लिए पठनीय बनाना चाहते, setIntervalआप के बारे में सीखना चाहते हैं new Date()और toLocaleTimeString()और आप इसे इतना पसंद लागू करना होगा:

class TimeComponent extends Component {
  state = { time: new Date().toLocaleTimeString() };
}

componentDidMount() {
  setInterval(() => {
   this.setState({ time: new Date().toLocaleTimeString() })    
  }, 1000)
}

ध्यान दें मैंने constructor()फ़ंक्शन को भी हटा दिया है , आपको इसकी आवश्यकता नहीं है, मेरा रिफ्लेक्टर constructor()फ़ंक्शन के साथ प्रारंभिक साइट के बराबर 100% है।


0

React V16 में परिवर्तन के कारण जहां घटकWillReceiveProps () को हटा दिया गया है, यह वह पद्धति है जिसका उपयोग मैं एक घटक को अपडेट करने के लिए करता हूं। ध्यान दें कि नीचे का उदाहरण टाइपस्क्रिप्ट में है और जब भी प्रॉप्स अपडेट होते हैं तो प्रारंभिक स्थिति और अद्यतन स्थिति प्राप्त करने के लिए स्थिर getDerivedStateFromProps विधि का उपयोग करता है।

    class SomeClass extends React.Component<Props, State> {
  static getDerivedStateFromProps(nextProps: Readonly<Props>): Partial<State> | null {
    return {
      time: nextProps.time
    };
  }

  timerInterval: any;

  componentDidMount() {
    this.timerInterval = setInterval(this.tick.bind(this), 1000);
  }

  tick() {
    this.setState({ time: this.props.time });
  }

  componentWillUnmount() {
    clearInterval(this.timerInterval);
  }

  render() {
    return <div>{this.state.time}</div>;
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.