implementation के बजाय व्यवहार का परीक्षण करें, StrictMode के दोहरे invocations का लाभ उठाएँ, और Profiler के साथ renders मापें।
इस पाठ को Kodokon में खोलेंTesting Library का दर्शन एक वाक्य में समा जाता है: उसका परीक्षण करें जो उपयोगकर्ता अनुभव करता है, कभी implementation विवरणों का नहीं। ठोस रूप से, आप DOM को accessibility tree के माध्यम से query करते हैं: पहले getByRole (queries की रानी, जो साथ-साथ आपकी ARIA roles को मान्य करती है), फिर getByLabelText, getByText, और getByTestId केवल अंतिम उपाय के रूप में। अंतःक्रियाओं के लिए, fireEvent के बजाय user-event को प्राथमिकता दें: जहाँ fireEvent.change एक अलग event उत्सर्जित करता है, वहीं user.type पूरा क्रम पुनरुत्पन्न करता है (focus, keydown, keypress, input, keyup), ठीक एक असली keyboard की तरह। findBy* variants एक query को एक async प्रतीक्षा के साथ जोड़ते हैं: किसी loading चरण के बाद आवश्यक।
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('adds a task to the list', async () => {
const user = userEvent.setup();
render(<TodoApp />);
await user.type(
screen.getByRole('textbox'),
'Review the report'
);
await user.click(
screen.getByRole('button', { name: /add/i })
);
expect(
await screen.findByText('Review the report')
).toBeInTheDocument();
});StrictMode एक development उपकरण है जिसका production में बिल्कुल कोई प्रभाव नहीं होता। development में, यह आपके component functions, state initializers, और setState को पास किए गए functions को दो बार call करता है, अशुद्ध renders को बाहर निकालने के लिए: अगर दो executions अलग परिणाम देते हैं, तो आपके पास एक छिपा हुआ side effect है। React 18 से, यह हर effect को mount, unmount, remount चक्र से भी गुज़ारता है: एक effect जिसकी cleanup पूरी तरह सममित नहीं है (कभी रद्द न की गई subscription, कभी abort न की गई request) तुरंत अपनी पोल खोल देता है। यह उन features की सीधी तैयारी है जहाँ React किसी screen की state को सुरक्षित रखते हुए उसे unmount फिर remount करता है।
useEffect(() => {
const controller = new AbortController();
fetch('/api/user', { signal: controller.signal })
.then((res) => res.json())
.then(setUser)
.catch(() => {});
return () => controller.abort();
}, []);मापने के लिए, React <Profiler> component और DevTools में उसका ग्राफ़िकल समकक्ष प्रदान करता है। उसका onRender callback, अन्य बातों के अलावा, phase (mount, update, या nested-update), actualDuration (इस commit के लिए subtree को render करने में वास्तव में लगा समय), और baseDuration (बिना किसी memoization के पूरे subtree को render करने के समय का एक अनुमान) प्राप्त करता है। दोनों के बीच का अंतर आपके memo और useMemo की प्रभावशीलता को मापता है: baseDuration से बहुत कम actualDuration का मतलब है कि memoization आपके लिए काम कर रहा है।
import { Profiler } from 'react';
function App() {
return (
<Profiler
id="Sidebar"
onRender={(id, phase, actualDuration) => {
console.log(id, phase, actualDuration);
}}
>
<Sidebar />
</Profiler>
);
}baseDuration क्या दर्शाता है?