앞에서는 javascript의 promises 의 then과 catch 블록을 사용했음.
하지만, then() 대신에 async/await statement를 react에서 data를 fetch할 때 사용할 수 있다.
import React, { Component } from 'react';
import axios from 'axios';
const API = 'https://hn.algolia.com/api/v1/search?query=';
const DEFAULT_QUERY = 'redux';
class App extends Component {
...
async componentDidMount() {
this.setState({ isLoading: true });
try {
const result = await axios.get(API + DEFAULT_QUERY);
this.setState({
hits: result.data.hits,
isLoading: false
});
} catch (error) {
this.setState({
error,
isLoading: false
});
}
}
...
}
export default App;
async (비동기)
await 문은 무언가가 비동기 적으로 실행될 때마다 비동기 함수 내에서 사용됩니다. 따라서 대기 한 요청이 해결되기 전에 다음 줄이 실행되지 않습니다. 또한 요청이 실패 할 경우 try 및 catch 블록을 사용하여 오류를 포착 할 수 있습니다.
반복되는 fetch 작업을 줄이자.(컴포넌트가 많아질수록 많아짐)
component가 mount될 때, data를 fetch하고 loading중, 이나 error 를 표시하는 거를 보여주고 싶음.
2가지 책임으로 componet가 잘라질 수 있는데,
showing the fetched data with conditional renderings and fetching the remote data with storing it in local state afterward. Whereas the former is only there for rendering purposes, the latter could be made reusable by a higher-order component.
> 리팩토링할 때 !
https://www.robinwieruch.de/react-higher-order-components/
const API = 'https://hn.algolia.com/api/v1/search?query=';
const DEFAULT_QUERY = 'redux';
...
const RenderPropApproach = () =>
<Fetcher url={API + DEFAULT_QUERY}>
{({ data, isLoading, error }) => {
if (!data) {
return <p>No data yet ...</p>;
}
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<ul>
{data.hits.map(hit =>
<li key={hit.objectID}>
<a href={hit.url}>{hit.title}</a>
</li>
)}
</ul>
);
}}
</Fetcher>
https://www.robinwieruch.de/react-hooks-fetch-data
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
};
fetchData();
}, []); //렌더링 최초에만
return (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
);
}
export default App;
- query가 바뀔 때만, 다시 fetch
default로 query값 저장.
loading중, error처리
import React, { Fragment, useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState('redux');
const [url, setUrl] = useState(
'https://hn.algolia.com/api/v1/search?query=redux',
);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(url);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
fetchData();
}, [url]);
return (
<Fragment>
<input
type="text"
value={query}
onChange={event => setQuery(event.target.value)}
/>
<button
type="button"
onClick={() =>
setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`)
}
>
Search
</button>
{isError && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)}
</Fragment>
);
}
export default App;
custom data fetching in hook 부터~ 시작!
[React] Virtual-DOM, Reconciliation, fiber (0) | 2021.06.21 |
---|---|
[MongoDB] Model Relationships Between Documents (3) (0) | 2021.06.10 |
[MongoDB] Model Relationships Between Documents (2) (0) | 2021.06.10 |
[MongoDB] Model Relationships Between Documents (1) (0) | 2021.06.10 |
[React] Fetch data in React (1) (0) | 2021.05.27 |
댓글 영역