एक प्रतिक्रिया एप्लिकेशन में सेटइंटरवाल


103

मैं अभी भी रिएक्ट में काफी नया हूं, लेकिन मैं धीरे-धीरे पीस रहा हूं और मैंने कुछ का सामना किया है जो मैं फंस गया हूं।

मैं प्रतिक्रिया में एक "टाइमर" घटक बनाने की कोशिश कर रहा हूं, और ईमानदार होने के लिए मुझे नहीं पता कि क्या मैं यह अधिकार (या कुशलतापूर्वक) कर रहा हूं। नीचे मेरी कोड में, मैं एक वस्तु वापस जाने के लिए राज्य की स्थापना की { currentCount: 10 }और साथ कर रहा है componentDidMount, componentWillUnmountऔर renderऔर मैं केवल 10 से 9 तक "उलटी गिनती" करने के लिए राज्य प्राप्त कर सकते हैं।

दो-भाग का प्रश्न: मैं क्या गलत कर रहा हूँ? और, वहाँ setTimeout का उपयोग कर (बजाय का उपयोग कर के बारे में जाने के लिए एक अधिक कुशल तरीका है componentDidMountऔर componentWillUnmount)?

पहले ही, आपका बहुत धन्यवाद।

import React from 'react';

var Clock = React.createClass({

  getInitialState: function() {
    return { currentCount: 10 };
  },

  componentDidMount: function() {
    this.countdown = setInterval(this.timer, 1000);
  },

  componentWillUnmount: function() {
    clearInterval(this.countdown);
  },

  timer: function() {
    this.setState({ currentCount: 10 });
  },

  render: function() {
    var displayCount = this.state.currentCount--;
    return (
      <section>
        {displayCount}
      </section>
    );
  }

});

module.exports = Clock;

2
bind(this)अब जरूरत नहीं है, प्रतिक्रिया अब अपने दम पर करती है।
डेरेक पोलार्ड

2
आपका टाइमर तरीका करंट अपडेट नहीं करता है
ब्रायन चेन

1
@ डेरेक आप निश्चित हैं? मैं बस इस काम के this.timer.bind(this)रूप में जोड़कर मेरा काम कर रहा हूँ। यह अपने आप में काम नहीं किया है
कीड़ा

6
@ Theworm @ डेरेक गलत है, तरह का। React.createClass (जो पदावनत है) ऑटोबाइंड के तरीके, लेकिन class Clock extends Componentऑटो बाइंड नहीं करता है। तो यह इस बात पर निर्भर करता है कि आप अपने घटकों को कैसे बना रहे हैं, क्या आपको बाँधने की आवश्यकता है।
CallMeNorm

जवाबों:


160

मैं आपके कोड के साथ 4 मुद्दे देखता हूं:

  • आपकी टाइमर विधि में आप हमेशा अपनी वर्तमान संख्या 10 पर सेट कर रहे हैं
  • आप रेंडर पद्धति में स्थिति को अपडेट करने का प्रयास करते हैं
  • आप setStateवास्तव में राज्य को बदलने के लिए विधि का उपयोग नहीं करते हैं
  • आप राज्य में अपना अंतराल नहीं जमा रहे हैं

चलो ठीक करने की कोशिश करते हैं:

componentDidMount: function() {
   var intervalId = setInterval(this.timer, 1000);
   // store intervalId in the state so it can be accessed later:
   this.setState({intervalId: intervalId});
},

componentWillUnmount: function() {
   // use intervalId from the state to clear the interval
   clearInterval(this.state.intervalId);
},

timer: function() {
   // setState method is used to update the state
   this.setState({ currentCount: this.state.currentCount -1 });
},

render: function() {
    // You do not need to decrease the value here
    return (
      <section>
       {this.state.currentCount}
      </section>
    );
}

यह 10 से -N तक घटने वाले टाइमर में परिणत होगा। यदि आप ऐसा टाइमर चाहते हैं जो 0 तक घट जाए, तो आप थोड़ा संशोधित संस्करण का उपयोग कर सकते हैं:

timer: function() {
   var newCount = this.state.currentCount - 1;
   if(newCount >= 0) { 
       this.setState({ currentCount: newCount });
   } else {
       clearInterval(this.state.intervalId);
   }
},

धन्यवाद। इसके बहुत सारे अर्थ निकलते हैं। मैं अभी भी बहुत शुरुआत कर रहा हूं और मैं कोशिश कर रहा हूं कि राज्य कैसे काम करता है और जो "चंक्स" में जाता है, जैसे रेंडर।
जोस

मैं सोच रहा हूं, हालांकि, क्या वास्तव में अंतराल सेट करने के लिए कंपोनेंटडिमाउंट और कंपोनेंटविल यूमाउंट का उपयोग करना आवश्यक है? संपादित करें: बस अपना सबसे हालिया संपादन देखा। :)
जोस

@ मुझे लगता componentDidMountहै कि ग्राहक पक्ष की घटनाओं को ट्रिगर करने के लिए सही जगह है, इसलिए मैं इसका उपयोग उलटी गिनती शुरू करने के लिए करूंगा। प्रारंभिक करने के लिए आप किस अन्य विधि के बारे में सोच रहे हैं?
डॉटनेट ३

मेरे पास विशेष रूप से कुछ और नहीं था, लेकिन यह एक घटक के अंदर इतने "विखंडू" का उपयोग करने के लिए भद्दा लग रहा था। मुझे लगता है कि यह सिर्फ खुद को आदी हो रहा है कि कैसे रिएक्ट में बिट्स और टुकड़े काम करते हैं। फिर से धन्यवाद!
जोस

4
राज्य के हिस्से के रूप में setInterval मान को संग्रहीत करने की कोई वास्तविक आवश्यकता नहीं है क्योंकि यह रेंडरिंग को प्रभावित नहीं करता है
Gil

32

10 सेकंड की उलटी गिनती का उपयोग कर अद्यतन किया गया class Clock extends Component

import React, { Component } from 'react';

class Clock extends Component {
  constructor(props){
    super(props);
    this.state = {currentCount: 10}
  }
  timer() {
    this.setState({
      currentCount: this.state.currentCount - 1
    })
    if(this.state.currentCount < 1) { 
      clearInterval(this.intervalId);
    }
  }
  componentDidMount() {
    this.intervalId = setInterval(this.timer.bind(this), 1000);
  }
  componentWillUnmount(){
    clearInterval(this.intervalId);
  }
  render() {
    return(
      <div>{this.state.currentCount}</div>
    );
  }
}

module.exports = Clock;

20

हुक का उपयोग करते हुए 10-सेकंड की उलटी गिनती अपडेट की गई (एक नया फीचर प्रस्ताव जो आपको क्लास लिखने के बिना राज्य और अन्य रिएक्ट सुविधाओं का उपयोग करने देता है। वे वर्तमान में रिएक्ट v16.7.0-अल्फा में हैं)।

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const Clock = () => {
    const [currentCount, setCount] = useState(10);
    const timer = () => setCount(currentCount - 1);

    useEffect(
        () => {
            if (currentCount <= 0) {
                return;
            }
            const id = setInterval(timer, 1000);
            return () => clearInterval(id);
        },
        [currentCount]
    );

    return <div>{currentCount}</div>;
};

const App = () => <Clock />;

ReactDOM.render(<App />, document.getElementById('root'));

रिएक्ट 16.8 के साथ, रिएक्ट हुक एक स्थिर रिलीज में उपलब्ध हैं।
ग्रेग हर्बोइकज

4

अगर किसी को सेटक्टटरवल लागू करने के लिए एक रिएक्ट हुक दृष्टिकोण की तलाश है। दान अब्रामोव ने अपने ब्लॉग पर इसके बारे में बात की । यदि आप कक्षा दृष्टिकोण सहित विषय के बारे में अच्छा पढ़ना चाहते हैं, तो इसे देखें। मूल रूप से कोड एक कस्टम हुक है जो कि घोषणापत्र के रूप में सेटलेट को बदल देता है।

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

सुविधा के लिए कोडसैंडबॉक्स लिंक भी पोस्ट करना: https://codesandbox.io/s/105x531vkq


2

धन्यवाद @dotnetom, @ greg-herbowicz

अगर यह "this.state अपरिभाषित है" लौटता है - बाइंड टाइमर फ़ंक्शन:

constructor(props){
    super(props);
    this.state = {currentCount: 10}
    this.timer = this.timer.bind(this)
}

0

प्रतिक्रिया वर्ग में हर पल अद्यतन स्थिति। मेरे सूचकांक पर ध्यान दें। जेएस एक फ़ंक्शन को पास करता है जो वर्तमान समय को वापस करता है।

import React from "react";

class App extends React.Component {
  constructor(props){
    super(props)

    this.state = {
      time: this.props.time,

    }        
  }
  updateMe() {
    setInterval(()=>{this.setState({time:this.state.time})},1000)        
  }
  render(){
  return (
    <div className="container">
      <h1>{this.state.time()}</h1>
      <button onClick={() => this.updateMe()}>Get Time</button>
    </div>
  );
}
}
export default App;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.