ã«ã¹ã¿ã ããã¯ã§å¹ççãã€ä¿å®æ§ã®é«ãReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ãã°ããŒãã«ãããžã§ã¯ãå šäœã§è€éãªããžãã¯ãæœåºããåå©çšã»å ±æããæ¹æ³ã解説ããŸãã
Reactã«ã¹ã¿ã ããã¯ïŒã°ããŒãã«éçºã«ãããããžãã¯ã®æœåºãšåå©çšã®ãã¹ã¿ãŒ
ããã³ããšã³ãéçºãç¹ã«Reactãšã³ã·ã¹ãã ã®ãã€ãããã¯ãªäžçã§ã¯ãå¹çæ§ãšä¿å®æ§ãæãéèŠã§ããã¢ããªã±ãŒã·ã§ã³ãè€éåããã«ã€ããŠãæ§ã ãªã³ã³ããŒãã³ãéã§å ±æããžãã¯ã管çããããšã¯å€§ããªèª²é¡ãšãªãåŸãŸãããŸãã«ããã§Reactã®ã«ã¹ã¿ã ããã¯ãç䟡ãçºæ®ããã¹ããŒããã«ãªããžãã¯ãæœåºã»åå©çšããããã®åŒ·åãªã¡ã«ããºã ãæäŸããŸãããã®å æ¬çãªã¬ã€ãã§ã¯ãã«ã¹ã¿ã ããã¯ãäœæãæŽ»çšããæè¡ãæãäžããäžçäžã®éçºè ãããå ç¢ã§ã¹ã±ãŒã©ãã«ããã€ä¿å®æ§ã®é«ãReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããããæ¯æŽããŸãã
Reactã«ãããããžãã¯å ±æã®é²å
ããã¯ãç»å Žãã以åãReactã§ã¹ããŒããã«ãªããžãã¯ãå ±æããã«ã¯ãäž»ã«é«éã³ã³ããŒãã³ãïŒHOCïŒãšRender Propsãšãã2ã€ã®ãã¿ãŒã³ã«äŸåããŠããŸããããããã®ãã¿ãŒã³ã¯å¹æçã§ãããããã°ãã°ãã©ãããŒå°çããã³ã³ããŒãã³ãã®ãã¹ãå¢å ã«ã€ãªãããã³ãŒãããŒã¹ã®å¯èªæ§ããããã°ãå°é£ã«ããŠããŸããã
é«éã³ã³ããŒãã³ãïŒHOCsïŒ
HOCã¯ãã³ã³ããŒãã³ããåŒæ°ãšããŠåãåããæ¡åŒµãããpropsãæ¯ãèããæã€æ°ããã³ã³ããŒãã³ããè¿ã颿°ã§ããäŸãã°ãããŒã¿ãã§ããã³ã°HOCã¯ããã§ããããããŒã¿ãšããŒãã£ã³ã°ç¶æ ãã³ã³ããŒãã³ãã®propsã«æäŸããŸãã
// Example of a conceptual HOC for data fetching
const withDataFetching = (WrappedComponent) => {
return class extends React.Component {
state = {
data: null,
loading: true,
error: null
};
async componentDidMount() {
try {
const response = await fetch('/api/data');
const data = await response.json();
this.setState({ data, loading: false });
} catch (error) {
this.setState({ error, loading: false });
}
}
render() {
return ;
}
};
};
// Usage:
const MyComponentWithData = withDataFetching(MyComponent);
æ©èœçã§ã¯ãããã®ã®ãHOCã¯propsã®è¡çªãè€éãªã³ã³ããŒãã³ãããªãŒãåŒãèµ·ããå¯èœæ§ããããŸããã
Render Props
Render Propsã¯ãã³ã³ããŒãã³ãã«propãšããŠé¢æ°ãæž¡ãããã®é¢æ°ãäœãã¬ã³ããªã³ã°ããããæ±ºå®ãããã¿ãŒã³ã§ãããã®ãã¿ãŒã³ã«ãããããžãã¯ãæã€ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãå¶åŸ¡ããããšã§ãããžãã¯ã®å ±æãå¯èœã«ãªããŸãã
// Example of a conceptual Render Prop component for mouse tracking
class MouseTracker extends React.Component {
state = { x: 0, y: 0 };
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
};
render() {
return (
{this.props.render(this.state)}
);
}
}
// Usage:
function App() {
return (
(
The mouse position is ({x}, {y})
)} />
);
}
Render Propsã¯HOCãããæè»æ§ããããŸããããè€æ°ã®ããžãã¯ãçµã¿åããããšããã¯ãæ·±ããã¹ãæ§é ã«ãªãå¯èœæ§ããããŸããã
ã«ã¹ã¿ã ããã¯ã®å°å ¥ïŒããžãã¯æœåºã®å
ã«ã¹ã¿ã ããã¯ã¯ãååããuseãã§å§ãŸããä»ã®ããã¯ãåŒã³åºãããšãã§ããJavaScript颿°ã§ãããããã¯ãã³ã³ããŒãã³ãã®ããžãã¯ãåå©çšå¯èœãªé¢æ°ã«æœåºããæ¹æ³ãæäŸããŸãããã®æœè±¡åã¯ãHOCãRender Propsã®æ§é çãªå¶çŽãªãã«ã¹ããŒããã«ãªããžãã¯ãæŽçã»å ±æããäžã§éåžžã«åŒ·åã§ãã
ã«ã¹ã¿ã ããã¯ãæ§æãããã®
- `use`ã§å§ãŸã: ãã®åœåèŠåã¯ãReactããã®é¢æ°ãããã¯ã§ãããšçè§£ããããã¯ã®ã«ãŒã«ïŒäŸïŒããã¯ã¯ãããã¬ãã«ã§ã®ã¿åŒã³åºããã«ãŒããæ¡ä»¶ããã¹ãããã颿°å ã§ã¯åŒã³åºããªãïŒã«åŸãå¿ èŠãããããšã瀺ãããã«éèŠã§ãã
- ä»ã®ããã¯ãåŒã³åºãã: ããããã®åã®æ žå¿ã§ããã«ã¹ã¿ã ããã¯ã¯ã
useState
ãuseEffect
ãuseContext
ãªã©ã®çµã¿èŸŒã¿Reactããã¯ãå©çšããŠãè€éãªããžãã¯ãã«ãã»ã«åã§ããŸãã - å€ãè¿ã: ã«ã¹ã¿ã ããã¯ã¯éåžžãã³ã³ããŒãã³ããå©çšã§ããå€ïŒç¶æ ã颿°ããªããžã§ã¯ãïŒãè¿ããŸãã
ã«ã¹ã¿ã ããã¯ã䜿çšããã¡ãªãã
- ã³ãŒãã®åå©çšæ§: æãæãããªã¡ãªããã§ããããžãã¯ãäžåºŠæžãã°ãã©ãã§ã䜿ããŸãã
- å¯èªæ§ãšæŽçã®åäž: è€éãªã³ã³ããŒãã³ãããžãã¯ãå€éšã«ç§»åãããããšã§ãã³ã³ããŒãã³ããããã¯ãªãŒã³ã§çè§£ãããããªããŸãã
- ãã¹ãã®å®¹æã: ã«ã¹ã¿ã ããã¯ã¯åãªãJavaScript颿°ã§ãããããäžè¬çã«ã³ã³ããŒãã³ããšæ¯èŒããŠç¬ç«ããŠãã¹ãããã®ã容æã§ãã
- è€éãªããžãã¯ã®æœè±¡å: ããŒã¿ãã§ããããã©ãŒã ãã³ããªã³ã°ããµãã¹ã¯ãªãã·ã§ã³ãã¢ãã¡ãŒã·ã§ã³ãªã©ã®é¢å¿äºãèªå·±å®çµåã®ãŠãããã«ã«ãã»ã«åããŸãã
- ç°ãªãã³ã³ããŒãã³ãã¿ã€ãéã§ã®ããžãã¯å ±æ: 以åã®æ¹æ³ãšã¯ç°ãªããã«ã¹ã¿ã ããã¯ã¯é¢æ°ã³ã³ããŒãã³ããšä»ã®ã«ã¹ã¿ã ããã¯ã®äž¡æ¹ã§äœ¿çšã§ããŸãã
æåã®ã«ã¹ã¿ã ããã¯ãäœæããïŒå®è·µçãªäŸ
ããããã·ããªãªãAPIããã®ããŒã¿ãã§ãããäŸã«ããã®æŠå¿µã説æããŸãããã
åé¡ïŒç¹°ãè¿ãçºçããããŒã¿ãã§ããããžãã¯
è€æ°ã®ã³ã³ããŒãã³ããç°ãªããšã³ããã€ã³ãããããŒã¿ããã§ããããå¿
èŠããããšæ³åããŠãã ãããã«ã¹ã¿ã ããã¯ããªããã°ãåã³ã³ããŒãã³ãã§useEffect
ããã¯ãšfetch
åŒã³åºããããŒãã£ã³ã°ã®ç¶æ
管çããšã©ãŒãã³ããªã³ã°ãç¹°ãè¿ãããšã«ãªãã§ãããã
解決çïŒ`useFetch`ã«ã¹ã¿ã ããã¯
ãã®ããžãã¯ãã«ãã»ã«åããããã«`useFetch`ããã¯ãäœæã§ããŸãã
// hooks/useFetch.js
import { useState, useEffect } from 'react';
const useFetch = (url, options) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url, options]); // Re-fetch if URL or options change
return { data, loading, error };
};
export default useFetch;
`useFetch`ããã¯ã®äœ¿çš
ããã§ãã³ã³ããŒãã³ãã¯ãã®ããã¯ãã¯ãªãŒã³ã«å©çšã§ããŸãïŒ
// components/UserProfile.js
import React from 'react';
import useFetch from '../hooks/useFetch';
function UserProfile({ userId }) {
const { data: user, loading, error } = useFetch(`/api/users/${userId}`);
if (loading) {
return Loading user profile...
;
}
if (error) {
return Error loading profile: {error.message}
;
}
return (
{user.name}
Email: {user.email}
{/* Render other user details */}
);
}
export default UserProfile;
// components/ProductDetails.js
import React from 'react';
import useFetch from '../hooks/useFetch';
function ProductDetails({ productId }) {
const { data: product, loading, error } = useFetch(`/api/products/${productId}`);
if (loading) {
return Loading product details...
;
}
if (error) {
return Error loading product: {error.message}
;
}
return (
{product.name}
Price: ${product.price}
Description: {product.description}
{/* Render other product details */}
);
}
export default ProductDetails;
ããŒã¿ãã§ããã®ããžãã¯ãå®å šã«æœè±¡åãããŠããããšã«æ³šç®ããŠãã ããã`UserProfile`ãš`ProductDetails`ã³ã³ããŒãã³ãã¯ãä»ããã§ãããããããŒã¿ã®ã¬ã³ããªã³ã°ã«ã®ã¿çŠç¹ãåœãŠãŠãããã¯ããã«ã·ã³ãã«ã«ãªã£ãŠããŸãã
é«åºŠãªã«ã¹ã¿ã ããã¯ã®ãã¿ãŒã³ãšèæ ®äºé
ã«ã¹ã¿ã ããã¯ã®æçšæ§ã¯ãåçŽãªããŒã¿ãã§ãããã¯ããã«è¶ ããŠããŸããããã§ã¯ãèæ ®ãã¹ãããé«åºŠãªãã¿ãŒã³ãšãã¹ããã©ã¯ãã£ã¹ã玹ä»ããŸãïŒ
1. ç¶æ 管çãšããžãã¯ã®ããã®ããã¯
ã«ã¹ã¿ã ããã¯ã¯ããã©ãŒã ãã³ããªã³ã°ãããŒãžããŒã·ã§ã³ãã€ã³ã¿ã©ã¯ãã£ããªèŠçŽ ãªã©ãè€éãªç¶æ æŽæ°ãã«ãã»ã«åããã®ã«åªããŠããŸãã
äŸïŒ`useForm`ããã¯
ãã®ããã¯ã¯ããã©ãŒã ã®ç¶æ ãå ¥åã®å€æŽãéä¿¡ããžãã¯ã管çã§ããŸãã
// hooks/useForm.js
import { useState, useCallback } from 'react';
const useForm = (initialValues) => {
const [values, setValues] = useState(initialValues);
const handleChange = useCallback((event) => {
const { name, value } = event.target;
setValues(prevValues => ({ ...prevValues, [name]: value }));
}, []);
const handleSubmit = useCallback((callback) => (event) => {
if (event) event.preventDefault();
callback(values);
}, [values]);
const resetForm = useCallback(() => {
setValues(initialValues);
}, [initialValues]);
return {
values,
handleChange,
handleSubmit,
resetForm,
setValues // To allow programmatic updates
};
};
export default useForm;
ã³ã³ããŒãã³ãã§ã®äœ¿çšäŸïŒ
// components/ContactForm.js
import React from 'react';
import useForm from '../hooks/useForm';
function ContactForm() {
const { values, handleChange, handleSubmit } = useForm({
name: '',
email: '',
message: ''
});
const onSubmit = (formData) => {
console.log('Form submitted:', formData);
// Typically, you'd send this to an API here
};
return (
);
}
export default ContactForm;
2. ãµãã¹ã¯ãªãã·ã§ã³ãšå¯äœçšã®ç®¡ç
ã«ã¹ã¿ã ããã¯ã¯ããµãã¹ã¯ãªãã·ã§ã³ïŒäŸïŒWebSocketãã€ãã³ããªã¹ããŒããã©ãŠã¶APIïŒã管çããããããé©åã«ã¯ãªãŒã³ã¢ãããããããšãä¿èšŒããã®ã«çæ³çã§ãã
äŸïŒ`useWindowSize`ããã¯
ãã®ããã¯ã¯ããã©ãŠã¶ãŠã£ã³ããŠã®å¯žæ³ã远跡ããŸãã
// hooks/useWindowSize.js
import { useState, useEffect } from 'react';
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
};
window.addEventListener('resize', handleResize);
// Cleanup function to remove the event listener
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // Empty dependency array ensures this effect runs only once on mount and cleanup on unmount
return windowSize;
};
export default useWindowSize;
ã³ã³ããŒãã³ãã§ã®äœ¿çšäŸïŒ
// components/ResponsiveComponent.js
import React from 'react';
import useWindowSize from '../hooks/useWindowSize';
function ResponsiveComponent() {
const { width, height } = useWindowSize();
return (
Window Dimensions
Width: {width}px
Height: {height}px
This component will adapt its rendering based on the window size.
);
}
export default ResponsiveComponent;
3. è€æ°ã®ããã¯ã®çµã¿åãã
ä»ã®ã«ã¹ã¿ã ããã¯ã䜿çšããã«ã¹ã¿ã ããã¯ãäœæãã匷åãªæœè±¡åã¬ã€ã€ãŒãæ§ç¯ããããšãã§ããŸãã
äŸïŒ`useFilteredList`ããã¯
ãã®ããã¯ã¯ãããŒã¿ãã§ãããšãã£ã«ã¿ãªã³ã°ããžãã¯ãçµã¿åãããããšãã§ããŸãã
// hooks/useFilteredList.js
import useFetch from './useFetch';
import { useState, useMemo } from 'react';
const useFilteredList = (url, filterKey) => {
const { data: list, loading, error } = useFetch(url);
const [filter, setFilter] = useState('');
const filteredList = useMemo(() => {
if (!list) return [];
return list.filter(item =>
item[filterKey].toLowerCase().includes(filter.toLowerCase())
);
}, [list, filter, filterKey]);
return {
items: filteredList,
loading,
error,
filter,
setFilter
};
};
export default useFilteredList;
ã³ã³ããŒãã³ãã§ã®äœ¿çšäŸïŒ
// components/UserList.js
import React from 'react';
import useFilteredList from '../hooks/useFilteredList';
function UserList() {
const { items: users, loading, error, filter, setFilter } = useFilteredList('/api/users', 'name');
if (loading) return Loading users...
;
if (error) return Error loading users: {error.message}
;
return (
setFilter(e.target.value)}
/>
{users.map(user => (
- {user.name} ({user.email})
))}
);
}
export default UserList;
4. éåææäœãšäŸåé¢ä¿ã®åŠç
ããã¯å
ã§éåææäœãç¹ã«æéãšãšãã«å€åããå¯èœæ§ã®ãããã®ïŒAPIãšã³ããã€ã³ããæ€çŽ¢ã¯ãšãªãªã©ïŒãæ±ãå Žåãç¡éã«ãŒããå€ãããŒã¿ãé²ãããã«useEffect
ã®äŸåé
åãæ£ãã管çããããšãéèŠã§ãã
ãã¹ããã©ã¯ãã£ã¹ïŒäŸåé¢ä¿ã倿Žãããå¯èœæ§ãããå Žåã¯ããããå«ããŸããå¯äœçšãäžåºŠã ãå®è¡ããå¿
èŠãããå Žåã¯ã空ã®äŸåé
åïŒ`[]`ïŒã䜿çšããŸããç¹å®ã®å€ã倿Žããããšãã«ãšãã§ã¯ããåå®è¡ããå¿
èŠãããå Žåã¯ããããã®å€ãå«ããŸããäžå¿
èŠã«åç
§ã倿Žãããå¯èœæ§ã®ããè€éãªãªããžã§ã¯ãã颿°ã«ã€ããŠã¯ãuseCallback
ãŸãã¯useMemo
ã䜿çšããŠããããå®å®ãããããšãæ€èšããŠãã ããã
5. æ±çšçã§èšå®å¯èœãªããã¯ã®äœæ
ã°ããŒãã«ããŒã ã倿§ãªãããžã§ã¯ãå šäœã§ã®åå©çšæ§ãæå€§åããã«ã¯ãã«ã¹ã¿ã ããã¯ãã§ããã ãæ±çšçã§èšå®å¯èœã«ããããšãç®æããŸããããã«ã¯ãèšå®ãªããžã§ã¯ããã³ãŒã«ããã¯ãåŒæ°ãšããŠåãå ¥ããããšãå€ããå©çšè ãã³ã¢ããžãã¯ã倿Žããããšãªãããã¯ã®æ¯ãèãã調æŽã§ããããã«ããŸãã
äŸïŒèšå®ä»ãã®`useApi`ããã¯
ããå ç¢ãª`useFetch`ã¯ãã¡ãœãããããããŒããªã¯ãšã¹ãããã£ãªã©ã®èšå®ãåãå ¥ãã`useApi`ã«ãªãå¯èœæ§ããããŸãã
// hooks/useApi.js
import { useState, useEffect, useCallback } from 'react';
const useApi = (endpoint, config = {}) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(endpoint, config);
if (!response.ok) {
throw new Error(`API error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}, [endpoint, JSON.stringify(config)]); // Stringify config to ensure it's a stable dependency
useEffect(() => {
fetchData();
}, [fetchData]); // fetchData is memoized by useCallback
return { data, loading, error, refetch: fetchData };
};
export default useApi;
ããã«ãããããã¯ã¯POSTãªã¯ãšã¹ããç°ãªãããããŒãªã©ãããŸããŸãªAPIã€ã³ã¿ã©ã¯ã·ã§ã³ã«ããé©å¿å¯èœã«ãªããããã¯ãšã³ãèŠä»¶ã倿§ãªåœéãããžã§ã¯ãã«ãšã£ãŠéèŠã§ãã
ã«ã¹ã¿ã ããã¯ã«é¢ããã°ããŒãã«ãªèæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
ã°ããŒãã«ãªå©çšè ã察象ã«ã«ã¹ã¿ã ããã¯ãéçºããéã«ã¯ã以äžã®ç¹ãèæ ®ããŠãã ããïŒ
- åœéåïŒi18nïŒ: ããã¯ãUIé¢é£ã®ããã¹ãããšã©ãŒã¡ãã»ãŒãžã管çããå Žåãi18næŠç¥ãšã·ãŒã ã¬ã¹ã«çµ±åã§ããããã«ããŠãã ãããããã¯å ã«æååãããŒãã³ãŒãã£ã³ã°ããã®ã§ã¯ãªããpropsãšããŠæž¡ãããcontextã䜿çšããŸãã
- å°ååïŒl10nïŒ: æ¥ä»ãæ°å€ãéè²šãæ±ãããã¯ã«ã€ããŠã¯ãããããæ£ããå°ååãããŠããããšã確èªããŠãã ãããReactã®
Intl
APIãdate-fns
ãnuml
ã®ãããªã©ã€ãã©ãªãã«ã¹ã¿ã ããã¯ã«çµ±åã§ããŸããäŸãã°ã`useFormattedDate`ããã¯ã¯ãã±ãŒã«ãšãã©ãŒããããªãã·ã§ã³ãåãå ¥ããããšãã§ããŸãã - ã¢ã¯ã»ã·ããªãã£ïŒa11yïŒ: ããã¯ã«ãã£ãŠç®¡çãããUIèŠçŽ ãã€ã³ã¿ã©ã¯ã·ã§ã³ãã¢ã¯ã»ã·ãã«ã§ããããšã確èªããŠãã ãããäŸãã°ãã¢ãŒãã«ããã¯ã¯ãã©ãŒã«ã¹ãæ£ãã管çããããŒããŒãã§æäœå¯èœã§ããã¹ãã§ãã
- ããã©ãŒãã³ã¹æé©å: äžå¿
èŠãªåã¬ã³ããªã³ã°ãèšç®ã«æ³šæããŠãã ããã
useMemo
ãšuseCallback
ãé©åã«äœ¿çšããŠãé«ã³ã¹ããªæäœãå®å®ãã颿°åç §ãã¡ã¢åããŸãã - å ç¢ãªãšã©ãŒãã³ããªã³ã°: å æ¬çãªãšã©ãŒãã³ããªã³ã°ãå®è£ ããŸããæå³ã®ãããšã©ãŒã¡ãã»ãŒãžãæäŸããã³ã³ããŒãã³ããç°ãªãã¿ã€ãã®ãšã©ãŒã«ã©ã®ããã«åå¿ãã¹ãããèæ ®ããŸãã
- ããã¥ã¡ã³ããŒã·ã§ã³: ã«ã¹ã¿ã ããã¯ãäœãããã®ãããã®ãã©ã¡ãŒã¿ãè¿ãå€ããããŠå¯äœçšãäŸåé¢ä¿ãæç¢ºã«ææžåããŸããããã¯ãç¹ã«åæ£ããã°ããŒãã«ããŒã ã§ã®ããŒã ã³ã©ãã¬ãŒã·ã§ã³ã«ãšã£ãŠäžå¯æ¬ ã§ããããè¯ãIDEçµ±åã®ããã«JSDocã³ã¡ã³ãã䜿çšããŸãã
- åœåèŠå: ãã¹ãŠã®ã«ã¹ã¿ã ããã¯ã«`use`ãã¬ãã£ãã¯ã¹ãå³å¯ã«éµå®ããŸããããã¯ã®ç®çãæç¢ºã«ç€ºãèšè¿°çãªååã䜿çšããŸãã
- ãã¹ãæŠç¥: ããã¯ãç¬ç«ããŠãã¹ãã§ããããã«èšèšããŸããReact Testing LibraryãJestãªã©ã®ãã¹ãã©ã€ãã©ãªãå©çšããŠãã«ã¹ã¿ã ããã¯ã®åäœãã¹ããäœæããŸãã
äŸïŒã°ããŒãã«Eã³ããŒã¹åãã®`useCurrency`ããã¯
äžçäžã§éå¶ãããŠããEã³ããŒã¹ãã©ãããã©ãŒã ãèããŠã¿ãŸãããã`useCurrency`ããã¯ã¯ããŠãŒã¶ãŒãéžæããé貚ã管çããäŸ¡æ Œã倿ããå°åã®æ £ç¿ã«åŸã£ãŠãã©ãŒãããããããšãã§ããŸãã
// hooks/useCurrency.js
import { useState, useContext, useMemo } from 'react';
import { CurrencyContext } from '../contexts/CurrencyContext'; // Assume a context for default currency/settings
const useCurrency = (amount = 0, options = {}) => {
const { defaultCurrency, exchangeRates } = useContext(CurrencyContext);
const { currency = defaultCurrency, locale = 'en-US' } = options;
const formattedAmount = useMemo(() => {
if (!exchangeRates || !exchangeRates[currency]) {
console.warn(`Exchange rate for ${currency} not found.`);
return `${amount} (Unknown Rate)`;
}
const convertedAmount = amount * exchangeRates[currency];
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,
}).format(convertedAmount);
}, [amount, currency, locale, exchangeRates]);
return formattedAmount;
};
export default useCurrency;
ãã®ããã¯ã¯ãå ±æèšå®ã®ããã«React ContextãæŽ»çšãããã©ãŠã¶ã®çµã¿èŸŒã¿åœéåAPIãå©çšããŠãã©ãŒããããåŠçãããããã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã«éåžžã«é©ããŠããŸãã
ã«ã¹ã¿ã ããã¯ãäœæãã¹ãã§ãªãå Žå
匷åã§ã¯ãããŸãããã«ã¹ã¿ã ããã¯ãåžžã«è§£æ±ºçã§ãããšã¯éããŸããã以äžã®ã·ããªãªãèæ ®ããŠãã ããïŒ
- åçŽãªããžãã¯: ããžãã¯ãåçŽã§ã1ã€ã2ã€ã®å Žæã§ãã䜿çšãããªãå ŽåãåçŽãªé¢æ°ã³ã³ããŒãã³ããçŽæ¥çãªå®è£ ã§ååãããããŸããã
- çŽç²ã«ãã¬ãŒã³ããŒã·ã§ãã«ãªããžãã¯: ããã¯ã¯ã¹ããŒããã«ãªããžãã¯ã®ããã®ãã®ã§ããpropsã倿ããã ãã§ãç¶æ ãã©ã€ããµã€ã¯ã«ãšãã§ã¯ãã䌎ããªãããžãã¯ã¯ãéåžžãã³ã³ããŒãã³ãèªäœãŸãã¯ãŠãŒãã£ãªãã£é¢æ°å ã«é 眮ããæ¹ãè¯ãã§ãã
- éå°ãªæœè±¡å: å°ãããŠäºçްãªããã¯ãããŸãã«ãå€ãäœæãããšã管çãããããããã²ãŒãããã®ãé£ãããæçåãããã³ãŒãããŒã¹ã«ã€ãªããå¯èœæ§ããããŸãã
çµè«ïŒReactã¯ãŒã¯ãããŒã匷åãã
Reactã«ã¹ã¿ã ããã¯ã¯ãReactã¢ããªã±ãŒã·ã§ã³ã«ãããããžãã¯ã®ç®¡çãšå ±æã®æ¹æ³ã«ãã©ãã€ã ã·ããããããããŸããéçºè ãã¹ããŒããã«ãªããžãã¯ãåå©çšå¯èœãªé¢æ°ã«æœåºã§ããããã«ããããšã§ãããã¯ãªãŒã³ãªã³ãŒããä¿é²ããä¿å®æ§ãé«ããéçºè ã®çç£æ§ãåäžãããŸããè€éãªã¢ããªã±ãŒã·ã§ã³ã«åãçµãã°ããŒãã«ããŒã ã«ãšã£ãŠãã«ã¹ã¿ã ããã¯ããã¹ã¿ãŒããããšã¯ãåãªããã¹ããã©ã¯ãã£ã¹ã§ã¯ãªããã¹ã±ãŒã©ãã«ã§å¹ççããã€å ç¢ãªãœãããŠã§ã¢ãæ§ç¯ããããã®å¿ é äºé ã§ãã
ã«ã¹ã¿ã ããã¯ãåãå ¥ããããšã§ãè€éããæœè±¡åãã宣èšçãªUIã«éäžããçè§£ããã¹ããé²åã容æãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãããã®ãã¿ãŒã³ãéçºã¯ãŒã¯ãããŒã«çµ±åããã«ã€ããŠãã³ãŒãã®èšè¿°éãæžãããã°ãæžå°ããããæŽç·Žãããæ©èœãããç°¡åã«æ§ç¯ã§ããããã«ãªãã§ããããçŸåšã®ãããžã§ã¯ãã§ç¹°ãè¿ãçŸããããžãã¯ãç¹å®ãããããåå©çšå¯èœãªã«ã¹ã¿ã ããã¯ã«å€æããæ¹æ³ãæ€èšããããšããå§ããŸããããæªæ¥ã®ããªãèªèº«ããããŠããªãã®ã°ããŒãã«ãªéçºããŒã ãæè¬ããã¯ãã§ãã