广çãªã³ã³ããŒãã³ããã¹ãã§å ç¢ãªReactã¢ããªã±ãŒã·ã§ã³ãå®çŸããŸãããããã®ã¬ã€ãã§ã¯ãã°ããŒãã«ãªéçºããŒã åãã«ã¢ãã¯å®è£ ãšåé¢ã®ãã¯ããã¯ãæ¢æ±ããŸãã
Reactã³ã³ããŒãã³ããã¹ãïŒã¢ãã¯å®è£ ãšåé¢ããã¹ã¿ãŒãã
ããã³ããšã³ãéçºã®ãã€ãããã¯ãªäžçã«ãããŠãReactã³ã³ããŒãã³ãã®ä¿¡é Œæ§ãšäºæž¬å¯èœæ§ã確ä¿ããããšã¯æãéèŠã§ããã¢ããªã±ãŒã·ã§ã³ãè€éåããã«ã€ããŠãå ç¢ãªãã¹ãæŠç¥ã®å¿ èŠæ§ããŸããŸãé«ãŸããŸãããã®å æ¬çãªã¬ã€ãã§ã¯ãç¹ã«ã¢ãã¯å®è£ ãšåé¢ã«çŠç¹ãåœãŠãReactã³ã³ããŒãã³ããã¹ãã®åºæ¬çãªæŠå¿µãæ·±ãæãäžããŸãããããã®ãã¯ããã¯ã¯ãå°ççãªå Žæãæåçèæ¯ã«é¢ä¿ãªããäžçäžã®éçºããŒã ã«å©çããããããååã«ãã¹ããããä¿å®å¯èœã§ã¹ã±ãŒã©ãã«ãªReactã¢ããªã±ãŒã·ã§ã³ãäœæããããã«äžå¯æ¬ ã§ãã
ã°ããŒãã«ããŒã ã«ãšã£ãŠã³ã³ããŒãã³ããã¹ããéèŠãªçç±
å°ççã«åæ£ããããŒã ã«ãšã£ãŠãäžè²«æ§ãšä¿¡é Œæ§ã®ãããœãããŠã§ã¢ã¯ãæåããã³ã©ãã¬ãŒã·ã§ã³ã®åºç€ã§ããã³ã³ããŒãã³ããã¹ãã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ã®åã ã®ãŠãããããã®äŸåé¢ä¿ããç¬ç«ããŠæåŸ éãã«åäœããããšãæ€èšŒããã¡ã«ããºã ãæäŸããŸãããã®åé¢ã«ãããç°ãªãã¿ã€ã ãŸãŒã³ã®éçºè ã¯ãèªåã®è²¢ç®ãä»ã®æ©èœãäºæããå£ãããšã¯ãªããšãã確信ãæã£ãŠãã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåã§äœæ¥ããããšãã§ããŸããããã«ã匷åãªãã¹ãã¹ã€ãŒãã¯çããããã¥ã¡ã³ããšããŠæ©èœããã³ã³ããŒãã³ãã®åäœãæç¢ºã«ããç°æåéã®ã³ãã¥ãã±ãŒã·ã§ã³ã§çãããèª€è§£ãæžãããŸãã
广çãªã³ã³ããŒãã³ããã¹ãã¯ã以äžã«è²¢ç®ããŸãïŒ
- ä¿¡é Œæ§ã®åäžïŒ éçºè ã¯ããé«ã確信ãæã£ãŠãªãã¡ã¯ã¿ãªã³ã°ãæ°æ©èœã®è¿œå ãè¡ããŸãã
- ãã°ã®åæžïŒ éçºãµã€ã¯ã«ã®æ©ã段éã§åé¡ãæããããšã§ãå€§å¹ ãªæéãšãªãœãŒã¹ãç¯çŽã§ããŸãã
- ã³ã©ãã¬ãŒã·ã§ã³ã®æ¹åïŒ æç¢ºãªãã¹ãã±ãŒã¹ã¯ãæ°ããããŒã ã¡ã³ããŒã®çè§£ãšãªã³ããŒãã£ã³ã°ãä¿é²ããŸãã
- ãã£ãŒãããã¯ã«ãŒãã®é«éåïŒ èªåãã¹ãã¯ã³ãŒãã®å€æŽã«å¯ŸããŠå³åº§ã«ãã£ãŒãããã¯ãæäŸããŸãã
- ä¿å®æ§ã®åäžïŒ ååã«ãã¹ããããã³ãŒãã¯ãæéãšãšãã«çè§£ãããããä¿®æ£ãããããªããŸãã
Reactã³ã³ããŒãã³ããã¹ãã«ãããåé¢ã®çè§£
ã³ã³ããŒãã³ããã¹ãã«ãããåé¢ãšã¯ãã³ã³ããŒãã³ãããã®å®éã®äŸåé¢ä¿ããåãé¢ããããå¶åŸ¡ãããç°å¢ã§ãã¹ããããã©ã¯ãã£ã¹ãæããŸããããã¯ãã³ã³ããŒãã³ããããåãããå€éšããŒã¿ãAPIã³ãŒã«ããŸãã¯åã³ã³ããŒãã³ãããã¢ãã¯ãã¹ã¿ããšããŠç¥ãããå¶åŸ¡ããã代æ¿ç©ã«çœ®ãæããããããšãæå³ããŸããäž»ãªç®æšã¯ãã³ã³ããŒãã³ãã®ããžãã¯ãšã¬ã³ããªã³ã°ãåé¢ããŠãã¹ãããç¹å®ã®å ¥åã«å¯ŸããŠãã®åäœãäºæž¬å¯èœã§ããã®åºåãæ£ããããšãä¿èšŒããããšã§ãã
APIãããŠãŒã¶ãŒããŒã¿ãååŸããReactã³ã³ããŒãã³ããèããŠã¿ãŸããããå®éã®ã·ããªãªã§ã¯ããã®ã³ã³ããŒãã³ãã¯ãµãŒããŒã«å¯ŸããŠHTTPãªã¯ãšã¹ããè¡ããŸãããããããã¹ãç®çã§ã¯ãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ããžãã¯ãå®éã®ãããã¯ãŒã¯ãªã¯ãšã¹ãããåé¢ããããšèããŸãããããã¯ãŒã¯ã®é å»¶ããµãŒããŒã®åæ¢ããŸãã¯APIããã®äºæããªãããŒã¿åœ¢åŒã«ãã£ãŠãã¹ãã倱æããããšã¯æãŸãããããŸãããããã§ãåé¢ãšã¢ãã¯å®è£ ãéåžžã«äŸ¡å€ã®ãããã®ã«ãªããŸãã
ã¢ãã¯å®è£ ã®å
ã¢ãã¯å®è£ ãšã¯ãã³ã³ããŒãã³ãã颿°ããŸãã¯ã¢ãžã¥ãŒã«ã®ä»£æ¿ããŒãžã§ã³ã§ãããå®éã® counterpartsïŒå¯Ÿå¿ç©ïŒã®åäœãæš¡å£ãã€ã€ããã¹ãç®çã§å¶åŸ¡å¯èœãªãã®ã§ããããã«ããã以äžã®ããšãå¯èœã«ãªããŸãïŒ
- ããŒã¿ã®å¶åŸ¡ïŒ ç¹å®ã®ããŒã¿ãã€ããŒããæäŸããŠãæ§ã ãªã·ããªãªïŒäŸïŒç©ºã®ããŒã¿ããšã©ãŒç¶æ ãå€§èŠæš¡ãªããŒã¿ã»ããïŒãã·ãã¥ã¬ãŒãããŸãã
- äŸåé¢ä¿ã®ã·ãã¥ã¬ãŒãïŒ APIã³ãŒã«ãã€ãã³ããã³ãã©ããã©ãŠã¶APIïŒäŸïŒ`localStorage`ã`setTimeout`ïŒãªã©ã®é¢æ°ãã¢ãã¯ããŸãã
- ããžãã¯ã®åé¢ïŒ å€éšã·ã¹ãã ããã®å¯äœçšãªãã«ãã³ã³ããŒãã³ãã®å éšããžãã¯ã®ãã¹ãã«éäžããŸãã
- ãã¹ãã®é«éåïŒ å®éã®ãããã¯ãŒã¯ãªã¯ãšã¹ããè€éãªéåææäœã®ãªãŒããŒããããåé¿ããŸãã
ã¢ãã¯æŠç¥ã®çš®é¡
Reactã®ãã¹ãã«ã¯ãããã€ãã®äžè¬çãªã¢ãã¯æŠç¥ããããŸãïŒ
1. åã³ã³ããŒãã³ãã®ã¢ãã¯
ãã°ãã°ã芪ã³ã³ããŒãã³ãã¯ããã€ãã®åã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããããããŸããã芪ããã¹ããããšããååã®è€éãªè©³çްããã¹ãããå¿ èŠã¯ãªããããããŸããã代ããã«ããã¬ãŒã¹ãã«ããŒãã¬ã³ããªã³ã°ããããäºæž¬å¯èœãªåºåãè¿ãããããåçŽãªã¢ãã¯ã³ã³ããŒãã³ãã«çœ®ãæããããšãã§ããŸãã
React Testing Libraryã䜿çšããäŸïŒ
UserProfileã³ã³ããŒãã³ããAvatarãšUserInfoã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããšããŸãããã
// UserProfile.js
import React from 'react';
import Avatar from './Avatar';
import UserInfo from './UserInfo';
function UserProfile({ user }) {
return (
);
}
export default UserProfile;
UserProfileãåé¢ããŠãã¹ãããããã«ãAvatarãšUserInfoãã¢ãã¯ã§ããŸããäžè¬çãªã¢ãããŒãã¯ãJestã®ã¢ãžã¥ãŒã«ã¢ãã¯æ©èœã䜿çšããããšã§ãã
// UserProfile.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserProfile from './UserProfile';
// Mocking child components using Jest
jest.mock('./Avatar', () => ({ imageUrl, alt }) => (
{alt}
));
jest.mock('./UserInfo', () => ({ name, email }) => (
{name}
{email}
));
describe('UserProfile', () => {
it('renders user details correctly with mocked children', () => {
const mockUser = {
id: 1,
name: 'Alice Wonderland',
email: 'alice@example.com',
avatarUrl: 'http://example.com/avatar.jpg',
};
render(<UserProfile user={mockUser} />);
// Assert that the mocked Avatar is rendered with correct props
const avatar = screen.getByTestId('mock-avatar');
expect(avatar).toBeInTheDocument();
expect(avatar).toHaveAttribute('data-image-url', mockUser.avatarUrl);
expect(avatar).toHaveTextContent(mockUser.name);
// Assert that the mocked UserInfo is rendered with correct props
const userInfo = screen.getByTestId('mock-user-info');
expect(userInfo).toBeInTheDocument();
expect(screen.getByText(mockUser.name)).toBeInTheDocument();
expect(screen.getByText(mockUser.email)).toBeInTheDocument();
});
});
ãã®äŸã§ã¯ãå®éã®AvatarãšUserInfoã³ã³ããŒãã³ãããç¹å®ã®`data-testid`屿§ãæã€`div`ãã¬ã³ããªã³ã°ããåçŽãªé¢æ°ã³ã³ããŒãã³ãã«çœ®ãæããŸãããããã«ãããUserProfileãåã³ã³ããŒãã³ãã«æ£ããpropsãæž¡ããŠããããšãããããã®åã®å
éšå®è£
ãç¥ãããšãªãæ€èšŒã§ããŸãã
2. APIã³ãŒã«ïŒHTTPãªã¯ãšã¹ãïŒã®ã¢ãã¯
APIããã®ããŒã¿ååŸã¯äžè¬çãªéåææäœã§ãããã¹ãã§ã¯ãã³ã³ããŒãã³ããããããæ£ããåŠçããããšã確èªããããã«ããããã®ã¬ã¹ãã³ã¹ãã·ãã¥ã¬ãŒãããå¿ èŠããããŸãã
Jestã¢ãã¯ã䜿çšãã`fetch`ïŒ
æçš¿ã®ãªã¹ããååŸããã³ã³ããŒãã³ããèããŠã¿ãŸãããïŒ
// PostList.js
import React, { useState, useEffect } from 'react';
function PostList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/posts')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
setPosts(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, []);
if (loading) return <p>Loading posts...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
export default PostList;
Jestã䜿çšããŠã°ããŒãã«ãª`fetch` APIãã¢ãã¯ã§ããŸãã
// PostList.test.js
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import PostList from './PostList';
// Mock the global fetch API
global.fetch = jest.fn();
describe('PostList', () => {
beforeEach(() => {
// Reset mocks before each test
fetch.mockClear();
});
it('displays loading message initially', () => {
render(<PostList />);
expect(screen.getByText('Loading posts...')).toBeInTheDocument();
});
it('displays posts after successful fetch', async () => {
const mockPosts = [
{ id: 1, title: 'First Post' },
{ id: 2, title: 'Second Post' },
];
// Configure fetch to return a successful response
fetch.mockResolvedValueOnce({
ok: true,
json: async () => mockPosts,
});
render(<PostList />);
// Wait for the loading message to disappear and posts to appear
await waitFor(() => {
expect(screen.queryByText('Loading posts...')).not.toBeInTheDocument();
});
expect(screen.getByText('First Post')).toBeInTheDocument();
expect(screen.getByText('Second Post')).toBeInTheDocument();
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith('/api/posts');
});
it('displays error message on fetch failure', async () => {
const errorMessage = 'Failed to fetch';
fetch.mockRejectedValueOnce(new Error(errorMessage));
render(<PostList />);
await waitFor(() => {
expect(screen.queryByText('Loading posts...')).not.toBeInTheDocument();
});
expect(screen.getByText(`Error: ${errorMessage}`)).toBeInTheDocument();
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith('/api/posts');
});
});
ãã®ã¢ãããŒãã«ãããæåããAPIã¬ã¹ãã³ã¹ãšå€±æããAPIã¬ã¹ãã³ã¹ã®äž¡æ¹ãã·ãã¥ã¬ãŒãã§ããã³ã³ããŒãã³ããç°ãªããããã¯ãŒã¯ç¶æ ãæ£ããåŠçããããšã確èªã§ããŸããããã¯ããããã¯ãŒã¯ã®ä¿¡é Œæ§ãå€åããå¯èœæ§ãããã°ããŒãã«ãªãããã€ã¡ã³ãã«ãããŠããšã©ãŒãé©åã«ç®¡çã§ããå埩åã®ããã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«éåžžã«éèŠã§ãã
3. ã«ã¹ã¿ã ããã¯ãšContextã®ã¢ãã¯
ã«ã¹ã¿ã ããã¯ãšReact Contextã¯åŒ·åãªããŒã«ã§ãããé©åã«æ±ããªããã°ãã¹ããè€éã«ããå¯èœæ§ããããŸããããããã¢ãã¯ããããšã§ããã¹ããç°¡çŽ åããã³ã³ããŒãã³ããšã®çžäºäœçšã«çŠç¹ãåœãŠãããšãã§ããŸãã
ã«ã¹ã¿ã ããã¯ã®ã¢ãã¯ïŒ
// useUserData.js (Custom Hook)
import { useState, useEffect } from 'react';
function useUserData(userId) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
setUser(data);
setLoading(false);
})
.catch(err => {
console.error('Error fetching user:', err);
setLoading(false);
});
}, [userId]);
return { user, loading };
}
export default useUserData;
// UserDetails.js (Component using the hook)
import React from 'react';
import useUserData from './useUserData';
function UserDetails({ userId }) {
const { user, loading } = useUserData(userId);
if (loading) return <p>Loading user...</p>;
if (!user) return <p>User not found.</p>;
return (
<div>
{user.name}
<p>{user.email}</p>
</div>
);
}
export default UserDetails;
`jest.mock`ã䜿çšããŠã«ã¹ã¿ã ããã¯ãã¢ãã¯ããã¢ãã¯å®è£ ãæäŸããããšãã§ããŸãã
// UserDetails.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserDetails from './UserDetails';
// Mock the custom hook
const mockUserData = {
id: 1,
name: 'Bob The Builder',
email: 'bob@example.com',
};
const mockUseUserData = jest.fn(() => ({ user: mockUserData, loading: false }));
jest.mock('./useUserData', () => mockUseUserData);
describe('UserDetails', () => {
it('displays user details when hook returns data', () => {
render(<UserDetails userId="1" />);
expect(screen.getByText('Loading user...')).not.toBeInTheDocument();
expect(screen.getByText('Bob The Builder')).toBeInTheDocument();
expect(screen.getByText('bob@example.com')).toBeInTheDocument();
expect(mockUseUserData).toHaveBeenCalledWith('1');
});
it('displays loading state when hook indicates loading', () => {
mockUseUserData.mockReturnValueOnce({ user: null, loading: true });
render(<UserDetails userId="2" />);
expect(screen.getByText('Loading user...')).toBeInTheDocument();
});
});
ããã¯ãã¢ãã¯ããããšã§ãããã¯ããè¿ãããç¶æ ãšããŒã¿ãå¶åŸ¡ã§ããã«ã¹ã¿ã ããã¯ã®ããžãã¯ã«äŸåããã³ã³ããŒãã³ãã®ãã¹ãã容æã«ãªããŸããããã¯ãè€éãªããžãã¯ãããã¯ã«æœè±¡åããããšãã³ãŒãã®æŽçãšåå©çšæ§ãåäžããã忣ããŒã ã«ãããŠç¹ã«æçšã§ãã
4. Context APIã®ã¢ãã¯
Contextãæ¶è²»ããã³ã³ããŒãã³ãããã¹ãããã«ã¯ãã¢ãã¯ã®Contextå€ãæäŸããå¿ èŠããããŸãã
// ThemeContext.js
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext({ theme: 'light', toggleTheme: () => {} });
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = React.useState('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
// ThemedButton.js (Component consuming context)
import React from 'react';
import { useTheme } from './ThemeContext';
function ThemedButton() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme} style={{ background: theme === 'light' ? '#eee' : '#333', color: theme === 'light' ? '#000' : '#fff' }}>
Switch to {theme === 'light' ? 'Dark' : 'Light'} Theme
</button>
);
}
export default ThemedButton;
ThemedButtonããã¹ãããããã«ãã¢ãã¯ã®ThemeProviderãäœæããããuseThemeããã¯ãã¢ãã¯ããããšãã§ããŸãã
// ThemedButton.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import ThemedButton from './ThemedButton';
// Mocking the useTheme hook
const mockToggleTheme = jest.fn();
jest.mock('./ThemeContext', () => ({
...jest.requireActual('./ThemeContext'), // Keep other exports if needed
useTheme: () => ({ theme: 'light', toggleTheme: mockToggleTheme }),
}));
describe('ThemedButton', () => {
it('renders with light theme and calls toggleTheme on click', () => {
render(<ThemedButton />);
const button = screen.getByRole('button', {
name: /Switch to Dark Theme/i,
});
expect(button).toHaveStyle('background-color: #eee');
expect(button).toHaveStyle('color: #000');
fireEvent.click(button);
expect(mockToggleTheme).toHaveBeenCalledTimes(1);
});
it('renders with dark theme when context provides it', () => {
// Mocking the hook to return dark theme
jest.spyOn(require('./ThemeContext'), 'useTheme').mockReturnValue({
theme: 'dark',
toggleTheme: mockToggleTheme,
});
render(<ThemedButton />);
const button = screen.getByRole('button', {
name: /Switch to Light Theme/i,
});
expect(button).toHaveStyle('background-color: #333');
expect(button).toHaveStyle('color: #fff');
// Clean up the mock for subsequent tests if needed
jest.restoreAllMocks();
});
});
Contextãã¢ãã¯ããããšã§ãã³ã³ããŒãã³ãã®åäœãåé¢ããç°ãªãContextå€ã«ã©ã®ããã«åå¿ãããããã¹ãã§ããæ§ã ãªç¶æ ã«ããã£ãŠäžè²«ããUIãä¿èšŒã§ããŸãããã®æœè±¡åã¯ãå€§èŠæš¡ãªå ±åãããžã§ã¯ãã«ãããä¿å®æ§ã®éµã§ãã
é©åãªãã¹ãããŒã«ã®éžæ
Reactã³ã³ããŒãã³ããã¹ãã«é¢ããŠã¯ãããã€ãã®ã©ã€ãã©ãªãå ç¢ãªãœãªã¥ãŒã·ã§ã³ãæäŸããŠããŸããéžæã¯ãã°ãã°ããŒã ã®å¥œã¿ããããžã§ã¯ãã®èŠä»¶ã«äŸåããŸãã
1. Jest
Jestã¯Facebookã«ãã£ãŠéçºããã人æ°ã®JavaScriptãã¹ããã¬ãŒã ã¯ãŒã¯ã§ããReactã§ãã䜿çšããã以äžãæäŸããŸãïŒ
- çµã¿èŸŒã¿ã®ã¢ãµãŒã·ã§ã³ã©ã€ãã©ãª
- ã¢ãã¯æ©èœ
- ã¹ãããã·ã§ãããã¹ã
- ã³ãŒãã«ãã¬ããž
- é«éãªå®è¡
2. React Testing Library
React Testing Library (RTL)ã¯ããŠãŒã¶ãŒãReactã³ã³ããŒãã³ããšå¯Ÿè©±ããæ¹æ³ã«äŒŒãæ¹æ³ã§ãã¹ãããã®ã«åœ¹ç«ã€ãŠãŒãã£ãªãã£ã®ã»ããã§ããå®è£ ã®è©³çްã§ã¯ãªããã³ã³ããŒãã³ãã®åäœããã¹ãããããšã奚å±ããŸããRTLã¯ä»¥äžã«çŠç¹ãåœãŠãŠããŸãïŒ
- ã¢ã¯ã»ã·ãã«ãªããŒã«ãããã¹ãã³ã³ãã³ãããŸãã¯ã©ãã«ã«ããèŠçŽ ã®ã¯ãšãª
- ãŠãŒã¶ãŒã€ãã³ãïŒã¯ãªãã¯ãã¿ã€ãã³ã°ïŒã®ã·ãã¥ã¬ãŒã·ã§ã³
- ã¢ã¯ã»ã·ãã«ã§ãŠãŒã¶ãŒäžå¿ã®ãã¹ãã®æšé²
RTLã¯Jestãšå®ç§ã«çµã¿åãããŠãå®å šãªãã¹ãã»ããã¢ãããæ§ç¯ã§ããŸãã
3. EnzymeïŒã¬ã¬ã·ãŒïŒ
Airbnbã«ãã£ãŠéçºãããEnzymeã¯ãReactã³ã³ããŒãã³ãããã¹ãããããã®äººæ°ã®ããéžæè¢ã§ãããReactã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ãæäœãã¢ãµãŒã·ã§ã³ã®ããã®ãŠãŒãã£ãªãã£ãæäŸããŠããŸããããŸã æ©èœããŸãããå®è£ ã®è©³çްã«çŠç¹ãåœãŠãŠããããšãRTLã®ç»å Žã«ãããçŸä»£ã®Reactéçºã§ã¯åŸè ã奜ãŸããããã«ãªããŸããããããžã§ã¯ãã§Enzymeã䜿çšããŠããå Žåããã®ã¢ãã¯æ©èœïŒ`shallow`ã`mount`ãš`mock`ã`stub`ã®çµã¿åãããªã©ïŒãçè§£ããããšã¯äŸç¶ãšããŠäŸ¡å€ããããŸãã
ã¢ãã¯ãšåé¢ã®ãã¹ããã©ã¯ãã£ã¹
ã³ã³ããŒãã³ããã¹ãæŠç¥ã®å¹æãæå€§åããããã«ã以äžã®ãã¹ããã©ã¯ãã£ã¹ãæ€èšããŠãã ããïŒ
- å®è£ ã§ã¯ãªããåäœããã¹ãããïŒ RTLã®å²åŠã«åŸãããŠãŒã¶ãŒã®ããã«èŠçŽ ãã¯ãšãªããŸããå éšç¶æ ããã©ã€ããŒãã¡ãœããã®ãã¹ãã¯é¿ããŠãã ãããããã«ããããã¹ãã¯ãªãã¡ã¯ã¿ãªã³ã°ã«å¯ŸããŠããå埩åãé«ãŸããŸãã
- ã¢ãã¯ã¯å ·äœçã«ïŒ ã¢ãã¯ãäœãããã¹ãããæç¢ºã«å®çŸ©ããŸããäŸãã°ãã¢ãã¯é¢æ°ã®æ»ãå€ãã¢ãã¯ã³ã³ããŒãã³ãã«æž¡ãããpropsãæå®ããŸãã
- å¿ èŠãªãã®ã ããã¢ãã¯ããïŒ éå°ã«ã¢ãã¯ããªãã§ãã ãããäŸåé¢ä¿ãåçŽã§ããããã³ã³ããŒãã³ãã®ã³ã¢ããžãã¯ã«ãšã£ãŠéèŠã§ãªãå Žåã¯ãéåžžéãã¬ã³ããªã³ã°ãããããã軜éãªã¹ã¿ãã䜿çšããããšãæ€èšããŠãã ããã
- èšè¿°çãªãã¹ãåã䜿çšããïŒ ãã¹ãã®èª¬æããç¹ã«ç°ãªãã¢ãã¯ã·ããªãªãæ±ãå Žåã«ãäœããã¹ãããŠããããæç¢ºã«è¿°ã¹ãŠããããšã確èªããŠãã ããã
- ã¢ãã¯ã®ã¹ã³ãŒããéå®ããïŒ ãã¹ããã¡ã€ã«ã®å é ã`describe`ãããã¯å ã§`jest.mock`ã䜿çšããŠã¢ãã¯ã®ã¹ã³ãŒãã管çããŸãã`beforeEach`ã`beforeAll`ã䜿çšããŠã¢ãã¯ãèšå®ãã`afterEach`ã`afterAll`ã§ã¯ãªãŒã³ã¢ããããŸãã
- ãšããžã±ãŒã¹ããã¹ãããïŒ ã¢ãã¯ã䜿çšããŠããšã©ãŒæ¡ä»¶ã空ã®ç¶æ ããã®ä»ã©ã€ãç°å¢ã§åçŸãé£ãããšããžã±ãŒã¹ãã·ãã¥ã¬ãŒãããŸããããã¯ãæ§ã ãªãããã¯ãŒã¯ç¶æ³ãããŒã¿æŽåæ§ã®åé¡ã«å¯ŸåŠããã°ããŒãã«ããŒã ã«ãšã£ãŠç¹ã«æçšã§ãã
- ã¢ãã¯ãææžåããïŒ ã¢ãã¯ãè€éã§ãããããã¹ããçè§£ããäžã§éèŠãªå Žåã¯ããã®ç®çã説æããã³ã¡ã³ãã远å ããŸãã
- ããŒã éã®äžè²«æ§ïŒ ã°ããŒãã«ããŒã å ã§ã¢ãã¯ãšåé¢ã«é¢ããæç¢ºãªã¬ã€ãã©ã€ã³ã確ç«ããŸããããã«ããããã¹ããžã®çµ±äžãããã¢ãããŒããä¿èšŒãããæ··ä¹±ãæžå°ããŸãã
ã°ããŒãã«éçºã«ããã課é¡ãžã®å¯ŸåŠ
忣ããŒã ã¯ãã°ãã°ç¹æã®èª²é¡ã«çŽé¢ããŸãããã³ã³ããŒãã³ããã¹ããšå¹æçãªã¢ãã¯ãçµã¿åãããããšã§ããããã軜æžããããšãã§ããŸãïŒ
- ã¿ã€ã ãŸãŒã³ã®éãïŒ åé¢ããããã¹ãã«ãããéçºè ã¯ãäºãããããã¯ããããšãªãã³ã³ããŒãã³ãã§åæã«äœæ¥ã§ããŸãã誰ããªã³ã©ã€ã³ã§ãããã«é¢ãããã倱æãããã¹ãã¯ããã«åé¡ãç¥ãããããšãã§ããŸãã
- å€åãããããã¯ãŒã¯ç¶æ³ïŒ APIã¬ã¹ãã³ã¹ãã¢ãã¯ããããšã§ãéçºè ã¯ç°ãªããããã¯ãŒã¯é床ãå®å šãªåæ¢ç¶æ ã§ã¢ããªã±ãŒã·ã§ã³ãã©ã®ããã«åäœãããããã¹ãã§ããã°ããŒãã«ã§äžè²«ãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãä¿èšŒã§ããŸãã
- UI/UXã«ãããæåçãªãã¥ã¢ã³ã¹ïŒ ã¢ãã¯ã¯æè¡çãªåäœã«çŠç¹ãåœãŠãŠããŸããã匷åãªãã¹ãã¹ã€ãŒãã¯ãUIèŠçŽ ãèšèšä»æ§ã«åŸã£ãŠæ£ããã¬ã³ããªã³ã°ãããããšãä¿èšŒããæåéã§èšèšèŠä»¶ã®èª€è§£ãçããå¯èœæ§ãæžãããŸãã
- æ°ããã¡ã³ããŒã®ãªã³ããŒãã£ã³ã°ïŒ ååã«ææžåãããåé¢ããããã¹ãã¯ãæ°ããããŒã ã¡ã³ããŒããã®èæ¯ã«é¢ããããã³ã³ããŒãã³ãã®æ©èœãçè§£ãã广çã«è²¢ç®ããããšã容æã«ããŸãã
çµè«
ç¹ã«å¹æçãªã¢ãã¯å®è£ ãšåé¢ã®ãã¯ããã¯ãéããŠReactã³ã³ããŒãã³ããã¹ããç¿åŸããããšã¯ãé«å質ã§ä¿¡é Œæ§ãé«ããä¿å®å¯èœãªReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®åºæ¬ã§ããã°ããŒãã«ãªéçºããŒã ã«ãšã£ãŠããããã®ãã©ã¯ãã£ã¹ã¯ã³ãŒãã®å質ãåäžãããã ãã§ãªããããè¯ãã³ã©ãã¬ãŒã·ã§ã³ãä¿é²ããçµ±åã®åé¡ãæžããã倿§ãªå°ççå Žæããããã¯ãŒã¯ç°å¢ã§äžè²«ãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãä¿èšŒããŸãã
åã³ã³ããŒãã³ããAPIã³ãŒã«ãã«ã¹ã¿ã ããã¯ãContextã®ã¢ãã¯ãªã©ã®æŠç¥ãæ¡çšãããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãéçºããŒã ã¯è¿ éã«ã€ãã¬ãŒã·ã§ã³ãè¡ããæã®è©Šç·Žã«èããå ç¢ãªUIãæ§ç¯ããããã«å¿ èŠãªèªä¿¡ãåŸãããšãã§ããŸããåé¢ãšã¢ãã¯ã®åãæŽ»çšããŠãäžçäžã®ãŠãŒã¶ãŒã«é¿ãåè¶ããReactã¢ããªã±ãŒã·ã§ã³ãäœæããŸãããã