मैं रिएक्टजेएस और जावास्क्रिप्ट सीख रहा हूं, और मुझे यह समस्या हुई है, मुझे नहीं पता कि यह ऐसा क्यों काम करता है, लेकिन मुझे लगता है कि मुझे पता है कि setEpisodeList के लिए राज्य सेट करके मेरा कार्य कई बार प्रतिपादन कर रहा है। बार-बार मुझे लगता है, मैं इसे अपने कोड में कैसे हल करूं?

info स्थिति में एक episodes ऑब्जेक्ट है जिसमें एक सरणी प्रकार है।

मेरे पास 1 सरणी में 1000 से अधिक एपिसोड हैं, इसलिए मैं उस 1 बड़े episodes सरणी को विभाजित करना चाहता हूं जिसमें 1000 से अधिक एपिसोड छोटे टुकड़ों में हों, प्रत्येक खंड एक सरणी होगी जिसमें 10 एपिसोड होंगे, इसलिए मैं हूं episodeListChunk.push(info.episodes.splice(0, 10)) का उपयोग करना।

तो यह बन जाएगा

[ 
 [chunk 1 - 10 episodes], 
 [chunk 2 - 10 episodes], 
 [chunk 3 - 10 episodes], 
 [chunk 4 - 10 episodes], ... 
]

अगर मैं console.log(episodeListChunk) का उपयोग करता हूं, तो मुझे लगता है कि यह ठीक काम कर रहा है।

What I want

लेकिन अगर मैं setEpisodeList(episodeListChunk) हूं तो मुझे बहुत सारे री-रेंडर मिलते हैं। क्या इसका मतलब यह है कि हर बार जब लूप चलता है तो यह हर बार सेटस्टेट करेगा? यदि ऐसा है, तो इन स्थितियों को संभालने के लिए मुझे कौन सा तरीका अपनाना चाहिए?

यहाँ मेरा कोड है:

function MovieWatch({ instance }) {
    const [info, setInfo] = useState([])
    const [done, setDone] = useState(false)
    const [episodeList, setEpisodeList] = useState([])

    let { slug } = useParams()

    const getInfo = async () => {
        const { data } = await instance.get("/getInfo?slug=" + slug)
        setInfo(data.data)
        setDone(true)
    }

    useEffect(() => {
        getInfo()
    }, [])

    const chunkEpisode = () => {
        const episodeListChunk = []
        while (info.episodes.length) {
            episodeListChunk.push(info.episodes.splice(0, 10))
        }
        setEpisodeList(episodeListChunk)
    }

    return (
        <>
            <div>Hello info page</div>
            {!done ? (
                <Loading loading={true} background="#000000" loaderColor="#FFFF00" />
            ) : (
                <>
                    {info ? chunkEpisode() : console.log("")}
                    <div>Done loading</div>
                </>
            )}
        </>
    )
}
2
Bunny 16 जिंदा 2022, 16:41
आप अपने एपिसोड का सिर्फ एक हिस्सा क्यों नहीं लाते, उन सभी को नहीं लाते। मुझे लगता है कि यह एक बेहतर तरीका है।
 – 
merko
16 जिंदा 2022, 16:49
@merko, मुझे कुछ और तरीके देने के लिए धन्यवाद, लेकिन क्या वास्तव में इसे फ्रंट-एंड में करने का कोई तरीका नहीं है? मैंने किसी को यह करते देखा है और मैं बस इसे आजमाना चाहता हूं। कुछ इस तरह: imgur.com/vnwnRFE
 – 
Bunny
16 जिंदा 2022, 16:54

5 जवाब

सबसे बढ़िया उत्तर

उपरोक्त में से कुछ उत्तरों को पढ़ने के बाद, मैंने पहली बार में 1 बड़ी सरणी बनाने की बजाय कोशिश की है, फिर जब भी पहली बार मुझे वह बड़ा सरणी प्राप्त होता है, तो मुझे नहीं पता कि मेरी व्याख्या सही है या नहीं। ..

chunkEpisode(data.data) का उपयोग करने के @Rejo मैथ्यू के तरीकों से, फिर मुझे आश्चर्य होता है कि info स्थिति को सेट करने का क्या मतलब है, इसलिए मैंने इसे हटा दिया, और @MWO के साथ @Steve K से समझाया, मैंने ऐसा करने की कोशिश की। यह अब ठीक काम कर रहा है।

लेकिन फिर भी, मैं अभी भी इसे इस तरह से नहीं करना चाहता, मुझे पहले वाले की तुलना में अजीब लगता है, क्योंकि पहला मुझे अच्छा लगता है, अजीब है कि यह काम क्यों नहीं कर रहा है।

setInfo के बजाय, फिर उस info का उपयोग फ़ंक्शन में लागू करने के लिए करें, मैं बस उस डेटा का उपयोग करता हूं जो मुझे इसे सेट किए बिना प्राप्त हुआ, फिर chunkEpisode को getInfo फ़ंक्शन में मर्ज करें, फिर useEffect का उपयोग केवल मेरे अनुमान के बाद ही कॉल करने के लिए करें।

मेरे द्वारा ऐसा करने के बाद कोड यहां दिया गया है:

function MovieWatch({ instance }) {
    const [done, setDone] = useState(false)
    const [episodeList, setEpisodeList] = useState([])

    let { slug } = useParams()

    const getInfo = async () => {
        const { data } = await instance.get("/getInfo?slug=" + slug)

        const episodeListChunk = []
        while (data.data.episodes.length) {
            episodeListChunk.push(data.data.episodes.splice(0, 10))
        }
        setEpisodeList(episodeListChunk)
        setDone(true)
    }

    useEffect(() => {
        getInfo()
    }, [])

    return (
        <>
            <div>Hello info page</div>
            {!done ? (
                <Loading loading={true} background="#000000" loaderColor="#FFFF00" />
            ) : (
                <>
                    {console.log(episodeList)}
                    <div>Done loading</div>
                </>
            )}
        </>
    )
}

परिणाम के बाद मैंने अपना कोड इस तरह बदल दिया।

Worked

लेकिन कृपया मुझे इसे अनुकूलित करने के लिए और सलाह दें।

0
Bunny 16 जिंदा 2022, 18:08

घटक प्रदान किए जाने पर आप जानकारी सेट कर रहे हैं। फिर आप जाँच कर रहे हैं कि जानकारी सेट है या नहीं और chunkEpisodes फ़ंक्शन चला रहा है। {info ? chunkEpisode() : console.log("")}। जानकारी हर बार सेट की जाएगी ताकि आप लगातार चंकएपिसोड फ़ंक्शन चला रहे हों। इस चेक को चलाने के बजाय आपको इसे एक उपयोग प्रभाव हुक में जानकारी के साथ एक निर्भरता के रूप में रखना चाहिए और यदि जानकारी सेट है तो चंकएपिसोड फ़ंक्शन चलाएं। इस तरह:

useEffect(() => {
  if(info){
    chunkEpisode()
  }
}, [info])
0
Steve K 16 जिंदा 2022, 16:53
हर बार जानकारी क्यों सेट की जाएगी?
 – 
MWO
16 जिंदा 2022, 16:57
क्योंकि जब घटक पहली बार आरोहित होता है तो आप getInfo चलाते हैं। फिर यह जानकारी सेट करता है और घटक को फिर से प्रस्तुत करता है। उसके बाद जानकारी सेट हो जाएगी ताकि आप यह देखने के लिए अपना चेक चलाएं कि जानकारी सेट है या नहीं और यह चंकएपिसोड फ़ंक्शन चलाता है। जो एपिसोड लिस्ट को सेट करता है और कंपोनेंट को री-रेंडर करता है। फिर आपका चेक फिर से चलता है और देखें कि जानकारी सेट हो गई है और बार-बार चंकएपिसोड फ़ंक्शन चलाता है।
 – 
Steve K
16 जिंदा 2022, 17:00
मैं देखता हूं कि जानकारी केवल एक बार सेट की जा रही है, और खंड एपिसोड() हर बार चलता है क्योंकि जानकारी अभी भी सेट है और राज्य एपिसोड सूची बदल गई है - लेकिन शायद हमारा मतलब वही है
 – 
MWO
16 जिंदा 2022, 17:04
अगर मैं ऐसा करता हूं तो यह info.episodes.length नहीं पढ़ सकता है और मुझे Can't perform a React state update on an unmounted component मिलता है, जिससे indicates a memory leak हो जाता है, और हां जैसे @MWO ने कहा, मुझे लगता है कि info केवल चलता है एक बार
 – 
Bunny
16 जिंदा 2022, 17:05
1
जानकारी केवल एक बार चल रही है और एक बार सेट की गई है। लेकिन हर बार जब आप किसी setState() को कॉल करते हैं तो कंपोनेंट फिर से रेंडर हो जाता है। तो आपकी जानकारी इस बिंदु पर निर्धारित की जाएगी। फिर आप जांचते हैं कि जानकारी सेट है या नहीं और chunkEpisode() फ़ंक्शन को कॉल करें और setState() फ़ंक्शन को उस घटक को फिर से प्रस्तुत करने के लिए कॉल करें। फिर आपका घटक फिर से प्रस्तुत करता है और जांचता है कि जानकारी सेट है या नहीं। यह है और आप chunkEpisode() फ़ंक्शन को बार-बार कॉल करते हैं। स्मृति रिसाव के लिए क्या आप इस घटक से दूर जा रहे हैं? ऐसा तब होता है जब आप किसी ऐसे घटक की स्थिति सेट करने का प्रयास कर रहे हैं जो अब उपलब्ध नहीं है।
 – 
Steve K
16 जिंदा 2022, 17:35

रिएक्ट में, हर बार जब कोई राज्य बदलता है तो पूरे घटक को फिर से प्रस्तुत किया जाता है।

जब ऐसा होता है तो रिएक्ट JSX के माध्यम से जाएगा और किसी भी राज्य में परिवर्तनों का पता लगाने और उन्हें फिर से प्रस्तुत करने का प्रयास करेगा।

चूंकि, आपने JSX में chunkEpisode() का आह्वान किया है, यह राज्य परिवर्तन यानी episodeList का कारण बन रहा है। राज्य परिवर्तन के कारण, JSX को फिर से प्रस्तुत किया जाता है, chunkEpisode() को फिर से लागू किया जाता है। यह असीम रूप से हो रहा है।

एक बेहतर तरीका यह होगा कि useEffect हुक का उपयोग करके chunkEpisode() का आह्वान किया जाए।

useEffect(() => {
    if (info) {
      chunkEpisode()
    }
}, [info])

और इस लाइन को हटा दें

{info ? chunkEpisode() : console.log("")}
0
Pawan Patel 16 जिंदा 2022, 16:59

प्रतिक्रिया प्राप्त करने और जानकारी सेट करने के बाद, डेटा के साथ चंकएपिसोड () को कॉल करें, बजाय इसे रिटर्न से कॉल करने के।

const getInfo = async () => {
    const { data } = await instance.get("/getInfo?slug=" + slug)
    setInfo(data.data)
    chunkEpisode(data.data)
    setDone(true)
}
0
Rejo Mathew 16 जिंदा 2022, 17:06
कृपया अपने वाक्य को थोड़ा और स्पष्ट करें।
 – 
Lies
16 जिंदा 2022, 20:11

मुझे लगता है कि आपकी समस्या info.episodes.splice(0, 10) में है। स्प्लिस सूचना स्थिति को बदल देता है और लगातार पुन: प्रस्तुत करने को ट्रिगर करता है।

यदि आप इसे इस तरह करते हैं तो आप देखेंगे कि त्रुटि समाप्त हो गई है और episodeList स्थिति अपडेट हो गई है।

तो इस बात पर निर्भर करता है कि आप स्लाइस के साथ क्या चाहते हैं, आप यहां से जा सकते हैं और नीचे दिए गए कोड को संशोधित कर सकते हैं:

function MovieWatch({ instance }) {
  const [info, setInfo] = useState([])
  const [done, setDone] = useState(false)
  const [episodeList, setEpisodeList] = useState([])

  let { slug } = useParams()

  const getInfo = async () => {
      const { data } = await instance.get("/getInfo?slug=" + slug)
      setInfo(data.data)
      setDone(true)
  }

  useEffect( () => {
    getInfo();
  }, [])

  const chunkEpisode = () => {
      const episodeListChunk = []
      // while (info.episodes.length) {
      //     episodeListChunk.push(info.episodes.splice(0, 10))
      // }
      info.episodes.forEach((e)=>{
        episodeListChunk.push(e)
      })
      console.log(episodeListChunk);
      setEpisodeList(episodeListChunk)
  }

  return (
      <>
          <div>Hello info page</div>
          {!done ? (
              <Loading loading={true} background="#000000" loaderColor="#FFFF00" />
          ) : (
              <>
                  {/* {info ? chunkEpisode() : console.log("")} */}
                  {episodeList.length ? episodeList : (chunkEpisode(), console.log(""))}
                  <div>Done loading</div>
              </>
          )}
      </>
  )
}
0
MWO 16 जिंदा 2022, 18:52
अगर मैं ऐसा करता हूं तो यह उसी मूल समस्या पर वापस आ जाएगा, मुझे Too many re-renders मिलता है
 – 
Bunny
16 जिंदा 2022, 17:21
धन्यवाद, @MWO, यह वास्तव में सभी error को साफ़ करता है, लेकिन क्या वैसे भी मैं episodeList स्थिति का उपयोग कर सकता हूं? अगर मैं console.log(episodeList) यह सिर्फ एक खाली [] सरणी लौटाता हूं
 – 
Bunny
16 जिंदा 2022, 17:52
1
मेरा जवाब अपडेट किया
 – 
MWO
16 जिंदा 2022, 18:53
मैंने स्वयं भी इसका उत्तर दिया है, लेकिन धन्यवाद, मैं आपका कोड आज़माउंगा, समस्या को हल करने में मेरी सहायता करने के लिए धन्यवाद
 – 
Bunny
16 जिंदा 2022, 18:58