ãšã©ãŒå¢çããã®ä»ã®å埩æŠç¥ãçšãããReactã¢ããªã±ãŒã·ã§ã³ã«ãããå ç¢ãªãšã©ãŒãã³ããªã³ã°å®è£ ã®å æ¬çã¬ã€ããã°ããŒãã«ãªãŠãŒã¶ãŒã«ã¹ã ãŒãºãªäœéšãæäŸããŸãã
Reactã®ãšã©ãŒãã³ããªã³ã°ïŒã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã®ããã®ãšã©ãŒå¢çãšå埩æŠç¥
å ç¢ã§ä¿¡é Œæ§ã®é«ãReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããšã¯ãç¹ã«å€æ§ãªãããã¯ãŒã¯ç¶æ³ãããã€ã¹ããŠãŒã¶ãŒè¡åãæã€ã°ããŒãã«ãªãŠãŒã¶ãŒã«ãµãŒãã¹ãæäŸããéã«éåžžã«éèŠã§ãã广çãªãšã©ãŒãã³ããªã³ã°ã¯ãã·ãŒã ã¬ã¹ã§ãããã§ãã·ã§ãã«ãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããã®æéèŠèª²é¡ã§ãããã®ã¬ã€ãã§ã¯ãå埩åã®ããã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«ãReactã®ãšã©ãŒå¢çïŒError BoundariesïŒããã®ä»ã®ãšã©ãŒå埩æŠç¥ã«ã€ããŠæ¢æ±ããŸãã
Reactã«ããããšã©ãŒãã³ããªã³ã°ã®éèŠæ§ãçè§£ãã
Reactã§æªåŠçã®ãšã©ãŒãçºçãããšãäºæãã¬ã¢ããªã±ãŒã·ã§ã³ã®ã¯ã©ãã·ã¥ãUIã®åŽ©å£ããããŠãã¬ãã£ããªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«ã€ãªããå¯èœæ§ããããŸããé©åã«èšèšããããšã©ãŒãã³ããªã³ã°æŠç¥ã¯ããããã®åé¡ãæªç¶ã«é²ãã ãã§ãªãããããã°ãã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§åäžã«åœ¹ç«ã€è²ŽéãªæŽå¯ãæäŸããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã®ã¯ã©ãã·ã¥ã鲿¢ïŒ ãšã©ãŒå¢çã¯ãåã³ã³ããŒãã³ãããªãŒå ã®ã©ããã§çºçããJavaScriptãšã©ãŒããã£ãããããããã®ãšã©ãŒããã°ã«èšé²ããã³ã³ããŒãã³ãããªãŒå šäœãã¯ã©ãã·ã¥ããã代ããã«ãã©ãŒã«ããã¯UIã衚瀺ããŸãã
- ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®åäžïŒ æçãªãšã©ãŒã¡ãã»ãŒãžãšäžå¯§ãªãã©ãŒã«ããã¯ãæäŸããããšã§ããŠãŒã¶ãŒã®æœåšçãªäžæºã管çå¯èœãªç¶æ³ã«å€ããããšãã§ããŸãã
- ãããã°ã®ä¿é²ïŒ 詳现ãªãšã©ãŒãã®ã³ã°ã䌎ãäžå çãªãšã©ãŒãã³ããªã³ã°ã¯ãéçºè ãåé¡ãè¿ éã«ç¹å®ãã察åŠããã®ã«åœ¹ç«ã¡ãŸãã
Reactã®ãšã©ãŒå¢çã®ç޹ä»
ãšã©ãŒå¢çïŒError BoundariesïŒã¯ãåã³ã³ããŒãã³ãããªãŒå ã®ã©ããã§çºçããJavaScriptãšã©ãŒããã£ãããããããã®ãšã©ãŒããã°ã«èšé²ãããã©ãŒã«ããã¯UIã衚瀺ããReactã³ã³ããŒãã³ãã§ãã以äžã®ãšã©ãŒã¯ãã£ããã§ããŸããïŒ
- ã€ãã³ããã³ãã©ïŒã€ãã³ããã³ãã©ã®ãšã©ãŒåŠçã«ã€ããŠã¯åŸè¿°ããŸãïŒ
- éåæã³ãŒãïŒäŸïŒ
setTimeoutãrequestAnimationFrameã®ã³ãŒã«ããã¯ïŒ - ãµãŒããŒãµã€ãã¬ã³ããªã³ã°
- ãšã©ãŒå¢çèªäœã§ã¹ããŒããããšã©ãŒïŒãã®åã³ã³ããŒãã³ãã§ã¯ãªãïŒ
ãšã©ãŒå¢çã³ã³ããŒãã³ãã®äœæ
ãšã©ãŒå¢çãäœæããã«ã¯ãstatic getDerivedStateFromError()ãŸãã¯componentDidCatch()ã©ã€ããµã€ã¯ã«ã¡ãœãããå®è£
ããã¯ã©ã¹ã³ã³ããŒãã³ããå®çŸ©ããŸããReact 16以éã颿°ã³ã³ããŒãã³ãã¯ãšã©ãŒå¢çã«ãªãããšãã§ããŸãããããã¯å°æ¥å€æŽãããå¯èœæ§ããããŸãã
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error("Caught error: ", error, errorInfo);
// Example: logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return (
Something went wrong.
{this.state.error && this.state.error.toString()}
{this.state.errorInfo && this.state.errorInfo.componentStack}
);
}
return this.props.children;
}
}
解説ïŒ
getDerivedStateFromError(error)ïŒ ãã®éçã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸããã¹ããŒããããšã©ãŒãåŒæ°ãšããŠåãåããstateãæŽæ°ããããã®å€ãè¿ãã¹ãã§ããcomponentDidCatch(error, errorInfo)ïŒ ãã®ã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸãã2ã€ã®åŒæ°ãåãåããŸãïŒerrorïŒ ã¹ããŒããããšã©ãŒãerrorInfoïŒ ã©ã®ã³ã³ããŒãã³ãããšã©ãŒãã¹ããŒãããã«é¢ããæ å ±ãå«ãcomponentStackããŒãæã€ãªããžã§ã¯ãã
ãšã©ãŒå¢çã®äœ¿çš
ä¿è·ãããã³ã³ããŒãã³ãããšã©ãŒå¢çã³ã³ããŒãã³ãã§ã©ããããŸãïŒ
MyComponentãŸãã¯ãã®åå«ã®ããããããšã©ãŒãã¹ããŒããå Žåããšã©ãŒå¢çãããããã£ãããããã©ãŒã«ããã¯UIãã¬ã³ããªã³ã°ããŸãã
ãšã©ãŒå¢çã®ç²åºŠ
è€æ°ã®ãšã©ãŒå¢çã䜿çšããŠãšã©ãŒãåé¢ããããšãã§ããŸããäŸãã°ãã¢ããªã±ãŒã·ã§ã³å šäœã«1ã€ã®ãšã©ãŒå¢çããç¹å®ã®ã»ã¯ã·ã§ã³ã«ãã1ã€ã®ãšã©ãŒå¢çãèšããããšãã§ããŸãããšã©ãŒå¢çã®é©åãªç²åºŠã決å®ããããã«ããŠãŒã¹ã±ãŒã¹ãæ éã«æ€èšããŠãã ããã
ãã®äŸã§ã¯ãUserProfileã§ã®ãšã©ãŒã¯ãã®ã³ã³ããŒãã³ããšãã®åã«ã®ã¿åœ±é¿ããã¢ããªã±ãŒã·ã§ã³ã®æ®ãã®éšåã¯æ©èœãç¶ããŸããGlobalNavigationãŸãã¯ArticleListã§ã®ãšã©ãŒã¯ãã«ãŒãã®ErrorBoundaryãããªã¬ãŒããããäžè¬çãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ããªããããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã®ä»ã®éšåã«ããã²ãŒãããèœåãä¿è·ããŸãã
ãšã©ãŒå¢çãè¶ ãããšã©ãŒãã³ããªã³ã°æŠç¥
ãšã©ãŒå¢çã¯äžå¯æ¬ ã§ãããæ¡çšãã¹ãå¯äžã®ãšã©ãŒãã³ããªã³ã°æŠç¥ã§ã¯ãããŸãããReactã¢ããªã±ãŒã·ã§ã³ã®å埩åãåäžãããããã®ä»ã®ããã€ãã®ãã¯ããã¯ã以äžã«ç€ºããŸãïŒ
1. try-catchæ
ã€ãã³ããã³ãã©ãéåææäœå
ãªã©ãç¹å®ã®ã³ãŒããããã¯ã§ãšã©ãŒãåŠçããããã«try-catchæã䜿çšããŸããReactã®ãšã©ãŒå¢çã¯ã€ãã³ããã³ãã©å
ã®ãšã©ãŒããã£ãã*ããªã*ããšã«æ³šæããŠãã ããã
const handleClick = () => {
try {
// Risky operation
doSomethingThatMightFail();
} catch (error) {
console.error("An error occurred: ", error);
// Handle the error, e.g., display an error message
setErrorMessage("An error occurred. Please try again later.");
}
};
åœéåã«é¢ããèæ
®äºé
ïŒ ãšã©ãŒã¡ãã»ãŒãžã¯ãŠãŒã¶ãŒã®èšèªã«ããŒã«ã©ã€ãºããå¿
èŠããããŸãã翻蚳ãæäŸããããã«i18nextã®ãããªããŒã«ãªãŒãŒã·ã§ã³ã©ã€ãã©ãªã䜿çšããŠãã ããã
import i18n from './i18n'; // Assuming you have i18next configured
const handleClick = () => {
try {
// Risky operation
doSomethingThatMightFail();
} catch (error) {
console.error("An error occurred: ", error);
// Use i18next to translate the error message
setErrorMessage(i18n.t('errorMessage.generic')); // 'errorMessage.generic' is a key in your translation file
}
};
2. éåæãšã©ãŒã®åŠç
APIããã®ããŒã¿ååŸãªã©ã®éåææäœã¯ãããŸããŸãªçç±ïŒãããã¯ãŒã¯ã®åé¡ããµãŒããŒãšã©ãŒãªã©ïŒã§å€±æããå¯èœæ§ããããŸããasync/awaitãšçµã¿åãããŠtry-catchãããã¯ã䜿çšããããPromiseã§ã®ãªãžã§ã¯ããåŠçããŸãã
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setData(data);
} catch (error) {
console.error("Fetch error: ", error);
setErrorMessage("Failed to fetch data. Please check your connection or try again later.");
}
};
// Alternative with Promises:
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
setData(data);
})
.catch(error => {
console.error("Fetch error: ", error);
setErrorMessage("Failed to fetch data. Please check your connection or try again later.");
});
ã°ããŒãã«ãªèŠç¹ïŒ APIãæ±ãéã«ã¯ããµãŒãã¹ãå©çšã§ããªããªã£ãå Žåã«é£éçãªé害ãé²ãããã«ããµãŒããããã¬ãŒã«ãŒãã¿ãŒã³ã®äœ¿çšãæ€èšããŠãã ãããããã¯ãå°åã«ãã£ãŠä¿¡é Œæ§ã®ã¬ãã«ãç°ãªãå¯èœæ§ã®ãããµãŒãããŒãã£ãµãŒãã¹ãšçµ±åããå Žåã«ç¹ã«éèŠã§ãã`opossum`ã®ãããªã©ã€ãã©ãªããã®ãã¿ãŒã³ã®å®è£ ã«åœ¹ç«ã¡ãŸãã
3. äžå çãªãšã©ãŒãã®ã³ã°
ã¢ããªã±ãŒã·ã§ã³å šäœã§ãšã©ãŒããã£ããã£ããŠè¿œè·¡ããããã®äžå çãªãšã©ãŒãã®ã³ã°ã¡ã«ããºã ãå®è£ ããŸããããã«ããããã¿ãŒã³ãç¹å®ãããã°ä¿®æ£ã®åªå é äœãä»ããã¢ããªã±ãŒã·ã§ã³ã®å¥å šæ§ãç£èŠããããšãã§ããŸããSentryãRollbarãBugsnagãªã©ã®ãµãŒãã¹ã®äœ¿çšãæ€èšããŠãã ããã
import * as Sentry from "@sentry/react";
import { BrowserTracing } from "@sentry/tracing";
Sentry.init({
dsn: "YOUR_SENTRY_DSN", // Replace with your Sentry DSN
integrations: [new BrowserTracing()],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 0.2,
environment: process.env.NODE_ENV,
release: "your-app-version",
});
const logErrorToSentry = (error, errorInfo) => {
Sentry.captureException(error, { extra: errorInfo });
};
class ErrorBoundary extends React.Component {
// ... (rest of the ErrorBoundary component)
componentDidCatch(error, errorInfo) {
logErrorToSentry(error, errorInfo);
}
}
ããŒã¿ãã©ã€ãã·ãŒïŒ ãã°ã«èšé²ããããŒã¿ã«æ³šæããŠãã ããããã©ã€ãã·ãŒèŠå¶ïŒäŸïŒGDPRãCCPAïŒã«éåããå¯èœæ§ã®ããæ©å¯æ§ã®é«ããŠãŒã¶ãŒæ å ±ããã°ã«èšé²ããããšã¯é¿ããŠãã ããããã°ã«èšé²ããåã«ãæ©å¯ããŒã¿ãå¿ååãŸãã¯å¢šå¡ãããããšãæ€èšããŠãã ããã
4. ãã©ãŒã«ããã¯UIãšã°ã¬ãŒã¹ãã«ãã°ã©ããŒã·ã§ã³
空çœã®ç»é¢ãäžå¯è§£ãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ãã代ããã«ãåé¡ã«ã€ããŠãŠãŒã¶ãŒã«éç¥ããèãããã解決çãææ¡ãããã©ãŒã«ããã¯UIãæäŸããŸããããã¯ãã¢ããªã±ãŒã·ã§ã³ã®éèŠãªéšåã«ãšã£ãŠç¹ã«éèŠã§ãã
const MyComponent = () => {
const [data, setData] = React.useState(null);
const [error, setError] = React.useState(null);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
fetchData()
.then(result => {
setData(result);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, []);
if (loading) {
return Loading...
;
}
if (error) {
return (
Error: {error.message}
Please try again later.
);
}
return Data: {JSON.stringify(data)}
;
};
5. 倱æãããªã¯ãšã¹ãã®å詊è¡
äžæçãªãšã©ãŒïŒäŸïŒäžæçãªãããã¯ãŒã¯ã®åé¡ïŒã®å Žåãçãé å»¶ã®åŸã«å€±æãããªã¯ãšã¹ããèªåçã«å詊è¡ããããšãæ€èšããŠãã ãããããã«ãããäžæçãªåé¡ããèªåçã«å埩ããããšã§ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäžãããããšãã§ããŸãã`axios-retry`ã®ãããªã©ã€ãã©ãªããã®ããã»ã¹ãç°¡çŽ åã§ããŸãã
import axios from 'axios';
import axiosRetry from 'axios-retry';
axiosRetry(axios, { retries: 3 });
const fetchData = async () => {
try {
const response = await axios.get('https://api.example.com/data');
return response.data;
} catch (error) {
console.error("Fetch error: ", error);
throw error; // Re-throw the error so the calling component can handle it
}
};
å«ççé æ ®ïŒ å詊è¡ã¡ã«ããºã ã¯è²¬ä»»ãæã£ãŠå®è£ ããŠãã ãããéå°ãªå詊è¡ã§ãµãŒãã¹ã«è² è·ãããããããšãåé¡ãæªåãããããµãŒãã¹æåŠïŒDoSïŒæ»æãšè§£éããããããå¯èœæ§ããããŸããå詊è¡éã®é å»¶ãåŸã ã«å¢ãããšã¯ã¹ããã³ã·ã£ã«ããã¯ãªãæŠç¥ã䜿çšããŠãã ããã
6. ãã£ãŒãã£ãŒãã©ã°
ãã£ãŒãã£ãŒãã©ã°ã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã®æ©èœãæ¡ä»¶ä»ãã§æå¹ãŸãã¯ç¡å¹ã«ããŸããããã«ãããæ°ããããŒãžã§ã³ã®ã³ãŒãããããã€ããããšãªããåé¡ã®ããæ©èœãè¿ éã«ç¡å¹ã«ããããšãã§ããŸããããã¯ãç¹å®ã®å°ççå°åã§åé¡ãçºçããå Žåã«ç¹ã«åœ¹ç«ã¡ãŸããLaunchDarklyãSplitãªã©ã®ãµãŒãã¹ããã£ãŒãã£ãŒãã©ã°ã®ç®¡çã«åœ¹ç«ã¡ãŸãã
import LaunchDarkly from 'launchdarkly-js-client-sdk';
const ldclient = LaunchDarkly.init('YOUR_LAUNCHDARKLY_CLIENT_ID', { key: 'user123' });
const MyComponent = () => {
const [isNewFeatureEnabled, setIsNewFeatureEnabled] = React.useState(false);
React.useEffect(() => {
ldclient.waitForInit().then(() => {
setIsNewFeatureEnabled(ldclient.variation('new-feature', false));
});
}, []);
if (isNewFeatureEnabled) {
return ;
} else {
return ;
}
};
ã°ããŒãã«ãªå±éïŒ ãã£ãŒãã£ãŒãã©ã°ã䜿çšããŠãæ°ããæ©èœãããŸããŸãªå°åããŠãŒã¶ãŒã»ã°ã¡ã³ãã«æ®µéçã«å±éããŸããããã«ãããæ©èœã®åœ±é¿ãç£èŠããå€ãã®ãŠãŒã¶ãŒã«åœ±é¿ãåã¶åã«åé¡ãè¿ éã«è§£æ±ºããããšãã§ããŸãã
7. å ¥åå€ã®æ€èšŒ
ã¯ã©ã€ã¢ã³ãåŽãšãµãŒããŒåŽã®äž¡æ¹ã§ãŠãŒã¶ãŒå ¥åãæ€èšŒããç¡å¹ãªããŒã¿ããšã©ãŒãåŒãèµ·ããã®ãé²ããŸããã¹ããŒãæ€èšŒã«ã¯YupãZodã®ãããªã©ã€ãã©ãªã䜿çšããŸãã
import * as Yup from 'yup';
const schema = Yup.object().shape({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(8, 'Password must be at least 8 characters').required('Required'),
});
const MyForm = () => {
const [email, setEmail] = React.useState('');
const [password, setPassword] = React.useState('');
const [errors, setErrors] = React.useState({});
const handleSubmit = async (e) => {
e.preventDefault();
try {
await schema.validate({ email, password }, { abortEarly: false });
// Submit the form
console.log('Form submitted successfully!');
} catch (err) {
const validationErrors = {};
err.inner.forEach(error => {
validationErrors[error.path] = error.message;
});
setErrors(validationErrors);
}
};
return (
);
};
ããŒã«ãªãŒãŒã·ã§ã³ïŒ æ€èšŒã¡ãã»ãŒãžããŠãŒã¶ãŒã®èšèªã«ããŒã«ã©ã€ãºãããŠããããšã確èªããŠãã ããããšã©ãŒã¡ãã»ãŒãžã®ç¿»èš³ãæäŸããããã«ãi18nextãŸãã¯åæ§ã®ã©ã€ãã©ãªã䜿çšããŸãã
8. ç£èŠãšã¢ã©ãŒã
ã¢ããªã±ãŒã·ã§ã³ã®ãšã©ãŒãç©æ¥µçã«æ€åºããŠå¯Ÿå¿ããããã«ãç£èŠãšã¢ã©ãŒããèšå®ããŸããPrometheusãGrafanaãDatadogãªã©ã®ããŒã«ã䜿çšããŠäž»èŠãªã¡ããªã¯ã¹ã远跡ãããããå€ãè¶ ãããšãã«ã¢ã©ãŒããããªã¬ãŒããŸãã
ã°ããŒãã«ç£èŠïŒ 忣ç£èŠã·ã¹ãã ã䜿çšããŠãããŸããŸãªå°ççå°åã§ã®ã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãšå¯çšæ§ã远跡ããããšãæ€èšããŠãã ãããããã«ãããå°åçãªåé¡ãããè¿ éã«ç¹å®ãã察åŠããã®ã«åœ¹ç«ã¡ãŸãã
Reactã«ããããšã©ãŒãã³ããªã³ã°ã®ãã¹ããã©ã¯ãã£ã¹
- ããã¢ã¯ãã£ãã§ããããšïŒ ãšã©ãŒãçºçããã®ãåŸ ããªãã§ãã ããããããžã§ã¯ãã®éå§æãããšã©ãŒãã³ããªã³ã°æŠç¥ãå®è£ ããŸãã
- å ·äœçã§ããããšïŒ é©åãªç²åºŠã§ãšã©ãŒããã£ããããŠåŠçããŸãã
- æçã§ããããšïŒ ãŠãŒã¶ãŒã«æç¢ºã§åœ¹ç«ã€ãšã©ãŒã¡ãã»ãŒãžãæäŸããŸãã
- äžè²«æ§ãæãããããšïŒ ã¢ããªã±ãŒã·ã§ã³å šäœã§äžè²«ãããšã©ãŒãã³ããªã³ã°ã¢ãããŒãã䜿çšããŸãã
- 培åºçã«ãã¹ãããããšïŒ ãšã©ãŒãã³ããªã³ã°ã³ãŒããæåŸ ã©ããã«æ©èœããããšã確èªããããã«ãã¹ãããŸãã
- ææ°æ å ±ã远ãããšïŒ Reactã®ææ°ã®ãšã©ãŒãã³ããªã³ã°æè¡ãšãã¹ããã©ã¯ãã£ã¹ã«åžžã«ç²ŸéããŠãããŸãã
çµè«
å
ç¢ãªãšã©ãŒãã³ããªã³ã°ã¯ãä¿¡é Œæ§ãé«ããŠãŒã¶ãŒãã¬ã³ããªãŒãªReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«äžå¯æ¬ ã§ããç¹ã«ã°ããŒãã«ãªãŠãŒã¶ãŒã«ãµãŒãã¹ãæäŸããå Žåã«ã¯éèŠã§ãããšã©ãŒå¢çãtry-catchæããã®ä»ã®ãšã©ãŒå埩æŠç¥ãå®è£
ããããšã§ããšã©ãŒãé©åã«åŠçããããžãã£ããªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸããã¢ããªã±ãŒã·ã§ã³ã®é·æçãªå®å®æ§ã確ä¿ããããã«ããšã©ãŒãã®ã³ã°ãç£èŠãããã³ããã¢ã¯ãã£ããªãã¹ããåªå
ããããšãå¿ããªãã§ãã ããããããã®ãã¯ããã¯ãæ
éãã€äžè²«ããŠé©çšããããšã§ãäžçäžã®ãŠãŒã¶ãŒã«é«å質ã®ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãã