मेरे पास एक फ़ंक्शन घटक है, और मैं इसे फिर से प्रस्तुत करने के लिए मजबूर करना चाहता हूं।
ऐसा मैं किस प्रकार करूं?
चूंकि कोई उदाहरण नहीं है this
, इसलिए मैं फोन नहीं कर सकता this.forceUpdate()
।
मेरे पास एक फ़ंक्शन घटक है, और मैं इसे फिर से प्रस्तुत करने के लिए मजबूर करना चाहता हूं।
ऐसा मैं किस प्रकार करूं?
चूंकि कोई उदाहरण नहीं है this
, इसलिए मैं फोन नहीं कर सकता this.forceUpdate()
।
जवाबों:
प्रतिक्रिया हुक का उपयोग करते हुए, अब आप useState()
अपने फ़ंक्शन घटक में कॉल कर सकते हैं ।
useState()
2 चीजों की एक सरणी लौटाएगा:
इसके सेटर द्वारा मूल्य को अपडेट करना आपके फ़ंक्शन घटक को फिर से प्रस्तुत करने के लिए बाध्य करेगा ,
जैसे forceUpdate
:
import React, { useState } from 'react';
//create your forceUpdate hook
function useForceUpdate(){
const [value, setValue] = useState(0); // integer state
return () => setValue(value => value + 1); // update the state to force render
}
function MyComponent() {
// call your hook here
const forceUpdate = useForceUpdate();
return (
<div>
{/*Clicking on the button will force to re-render like force update does */}
<button onClick={forceUpdate}>
Click to re-render
</button>
</div>
);
}
ऊपर दिया गया घटक कस्टम हुक फ़ंक्शन ( useForceUpdate
) का उपयोग करता है जो प्रतिक्रिया स्थिति हुक का उपयोग करता है useState
। यह घटक के राज्य के मूल्य में वृद्धि करता है और इस प्रकार घटक को फिर से प्रस्तुत करने के लिए रिएक्ट बताता है।
इस उत्तर के पुराने संस्करण में, स्निपेट ने बूलियन मूल्य का उपयोग किया, और इसमें टॉगल किया forceUpdate()
। अब जब मैंने अपना उत्तर संपादित कर लिया है, तो स्निपेट बूलियन के बजाय एक संख्या का उपयोग करता है।
क्यों ? (आप मुझसे पूछेंगे)
क्योंकि एक बार मेरे साथ ऐसा हुआ forceUpdate()
था कि मुझे दो अलग-अलग घटनाओं से बाद में दो बार बुलाया गया था, और इस प्रकार यह मूल स्थिति पर बूलियन मान को रीसेट कर रहा था, और घटक कभी भी प्रदान नहीं किया गया था।
ऐसा इसलिए है क्योंकि यहां के useState
सेटर ( setValue
यहां), React
पिछले राज्य की तुलना नए के साथ करते हैं, और केवल तभी प्रस्तुत करते हैं जब राज्य अलग हो।
forceUpdate
।
useState
हुक के बारे में बात कर रहे हैं , न कि वर्ग ' setState
जो वास्तव में एक तुलना नहीं करता है (जब तक आप को लागू नहीं करना चाहिए विधि)। वही डेमो देखें जो मैंने पोस्ट किया था, लेकिन setState
इसके लिए इस्तेमाल किए जाने वाले एक स्थिर मूल्य के साथ , यह फिर से रेंडर नहीं करता है: codeandbox.io/s/determined-rubin-8598l
अद्यतन प्रतिक्रिया v16.8 (16 फरवरी 2019 realease)
चूंकि 16.8 हुक के साथ जारी किया गया था , इसलिए फ़ंक्शन घटकों में अब लगातार पकड़ रखने की क्षमता है state
। कि क्षमता के साथ अब आप कर सकते हैं की नकल एक forceUpdate
:
ध्यान दें कि इस दृष्टिकोण पर फिर से विचार किया जाना चाहिए और ज्यादातर मामलों में जब आपको एक अपडेट को मजबूर करने की आवश्यकता होती है तो आप शायद कुछ गलत कर रहे हैं।
प्रतिक्रिया से पहले 16.8.0
नहीं, आप नहीं कर सकते, राज्य-कम फ़ंक्शन घटक केवल सामान्य हैं functions
जो रिटर्न करते हैं jsx
, आपके पास रिएक्ट जीवन चक्र विधियों तक कोई पहुंच नहीं है क्योंकि आप इसमें से विस्तार नहीं कर रहे हैं React.Component
।
फ़ंक्शन-घटक को render
वर्ग घटकों के विधि भाग के रूप में सोचें ।
props
या state
परिवर्तन नहीं होता है। आप रेंडर फ़ंक्शन को बाध्य नहीं कर सकते क्योंकि render
स्टेटलेस घटकों पर कोई फ़ंक्शन नहीं है । स्टेटलेस कंपोनेंट्स नहीं हैं कि extends
React.Component
वे सिर्फ सादे फंक्शन हैं जो रिटर्न करते हैं jsx
।
आधिकारिक अक्सर पूछे जाने वाले प्रश्न ( https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate ) अब इस तरह से अनुशंसा करता है यदि आपको वास्तव में करने की आवश्यकता है:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
const [, forceUpdate] = useReducer(x => x + 1, 0);
मैंने अपनी प्रतिक्रिया कार्यात्मक घटकों को प्रस्तुत करने के लिए बल -प्रयोग-अद्यतन नामक एक तृतीय पक्ष पुस्तकालय का उपयोग किया । आकर्षण की तरह काम किया। बस अपनी परियोजना में पैकेज का उपयोग करें और इस तरह का उपयोग करें।
import useForceUpdate from 'use-force-update';
const MyButton = () => {
const forceUpdate = useForceUpdate();
const handleClick = () => {
alert('I will re-render now.');
forceUpdate();
};
return <button onClick={handleClick} />;
};
useForceUpdate
उपयोग करता useCallback
है। यह दायित्व आपको कुछ कीस्ट्रोक्स से बचाने के लिए सिर्फ एक उपयोगिता है।
अस्वीकरण: समस्या के प्रति उत्तर नहीं।
यहां एक महत्वपूर्ण नोट छोड़ना:
यदि आप एक स्टेटलेस कंपोनेंट को बाध्य करने की कोशिश कर रहे हैं, तो संभावना है कि आपके डिजाइन में कुछ गड़बड़ है।
निम्नलिखित मामलों पर विचार करें:
यह स्पष्ट रूप से हुक का उपयोग किए बिना किया जा सकता है, बशर्ते आप अपने घटक और स्टेट को किसी घटक के मूल घटक में जोड़ दें:
const ParentComponent = props => {
const [updateNow, setUpdateNow] = useState(true)
const updateFunc = () => {
setUpdateNow(!updateNow)
}
const MyComponent = props => {
return (<div> .... </div>)
}
const MyButtonComponent = props => {
return (<div> <input type="button" onClick={props.updateFunc} />.... </div>)
}
return (
<div>
<MyComponent updateMe={updateNow} />
<MyButtonComponent updateFunc={updateFunc}/>
</div>
)
}
स्वीकृत उत्तर अच्छा है। बस इसे समझना आसान है।
उदाहरण घटक:
export default function MyComponent(props) {
const [updateView, setUpdateView] = useState(0);
return (
<>
<span style={{ display: "none" }}>{updateView}</span>
</>
);
}
नीचे दिए गए कोड को फिर से रेंडर करने के लिए मजबूर करने के लिए:
setUpdateView((updateView) => ++updateView);
इनमें से किसी ने भी मुझे संतोषजनक जवाब नहीं दिया, इसलिए अंत में मुझे वही मिला जो मुझे key
प्रोप, यूज़ रीफ और कुछ रैंडम आईडी जनरेटर के साथ चाहिए था shortid
।
मूल रूप से, मैं चाहता था कि कुछ चैट एप्लिकेशन पहली बार किसी को ऐप खोलने के लिए बाहर करें। तो, मुझे इस बात पर पूर्ण नियंत्रण की आवश्यकता थी कि कब और क्या जवाबों को async प्रतीक्षा के साथ अद्यतन किया जाए।
उदाहरण कोड:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ... your JSX functional component, import shortid somewhere
const [render, rerender] = useState(shortid.generate())
const messageList = useRef([
new Message({id: 1, message: "Hi, let's get started!"})
])
useEffect(()=>{
await sleep(500)
messageList.current.push(new Message({id: 1, message: "What's your name?"}))
// ... more stuff
// now trigger the update
rerender(shortid.generate())
}, [])
// only the component with the right render key will update itself, the others will stay as is and won't rerender.
return <div key={render}>{messageList.current}</div>
वास्तव में इसने मुझे एक चैट संदेश की तरह रोल करने की अनुमति दी।
const waitChat = async (ms) => {
let text = "."
for (let i = 0; i < ms; i += 200) {
if (messageList.current[messageList.current.length - 1].id === 100) {
messageList.current = messageList.current.filter(({id}) => id !== 100)
}
messageList.current.push(new Message({
id: 100,
message: text
}))
if (text.length === 3) {
text = "."
} else {
text += "."
}
rerender(shortid.generate())
await sleep(200)
}
if (messageList.current[messageList.current.length - 1].id === 100) {
messageList.current = messageList.current.filter(({id}) => id !== 100)
}
}