#reactjs
#reactjs
Вопрос:
Я пытаюсь загрузить некоторые компоненты в DOM после get
выполнения вызова. Консоль подтверждает, что компоненты загружены в переменную, но DOM не обновляется. Есть ли проблема с синтаксисом
const Blog: FC<BlogProps> = ({title, url}): ReactElement => {
let response = [];
let Posts = [];
const {isDarkMode} = useContext(ThemeContext);
function fetchBlogs(){
let url = url;
let count = 30;
axios({
method: 'post',
url: '/api/grabIt',
data: {
url: url,
count: count
}
})
.then(function (res) {
response = res.data.response;
Posts = response.map(async function (item, i) {
return (<li><Post category={item.type} title={item.title} author={item.by} image={item.url} link={item.url} key={i}/></li>)
})
})
.catch(function (error) {
console.log(error)
});
}
return (
<>
<div>
<Button buttonColor={!!isDarkMode}
onClick={fetchBlogs}
>FETCH</Button>
<ul>
{Posts}
</ul>
</div>
</>
)
};
export default Blog
Я также попытался просто создать массив, который определяется при загрузке компонента (а не после), и DOM по-прежнему не обновляется. Я просто получаю пустое <ul>
Комментарии:
1. Почему функция внутри
map
асинхронна? Он возвращает обещание, а не экземпляр компонента.2. Posts — это просто переменная, не имеющая отношения к состоянию компонента, React не знает, что ему нужно выполнить повторный запуск. измените сообщения, чтобы использовать React.useState
3. Вы могли бы добавить логику сопоставления внутри возврата и использовать состояния для его обновления. Есть ли причина избежать этого?
Ответ №1:
const Blog: FC<BlogProps> = ({ title, url }): ReactElement => {
let response = [];
const { isDarkMode } = useContext(ThemeContext);
const [list, setList] = React.useState([]);
function fetchBlogs() {
let url = url;
let count = 30;
axios({
method: 'post',
url: '/api/grabIt',
data: {
url: url,
count: count
}
})
.then(function (res) {
setList(res.data.response);
})
.catch(function (error) {
console.log(error)
});
}
return (
<>
<div>
<Button buttonColor={!!isDarkMode}
onClick={fetchBlogs}
>FETCH</Button>
<ul>
{list.map((item, i) => {
return <li key={`row-${i}`}>
<Post category={item.type} title={item.title} author={item.by} image={item.url} link={item.url} key={i} />
</li>;
})}
</ul>
</div>
</>
)
};
export default Blog
Ответ №2:
Во-первых, при создании нескольких тегов вы должны добавить key
к корневому элементу, который вы возвращаете.
Чтобы загрузить ваш список, вам нужно использовать useState
для вашего массива Posts.
Ответ №3:
Posts
это обычный массив, а не реактивный, в смысле React. Его изменение не вызовет повторной визуализации. Используйте useState
, чтобы сделать это реактивной переменной. Вы также должны map
проверять ответ синхронно, и на самом деле нет необходимости создавать компоненты здесь. Вместо этого сделайте это в инструкции return:
const Blog: FC<BlogProps> = ({title, url}): ReactElement => {
const [posts, setPosts] = React.useState([]);
const {isDarkMode} = useContext(ThemeContext);
function fetchBlogs() {
axios({
method: 'post',
url: '/api/grabIt',
data: { url, count: 30 }
})
.then(function (res) {
if (res.data.response) {
setPosts(res.data.response);
}
})
.catch(function (error) {
console.log(error)
});
}
return (
<>
<div>
<Button
buttonColor={!!isDarkMode}
onClick={fetchBlogs}
>
FETCH
</Button>
<ul>
{posts.map((post, i) => (
<li key={i}>
<Post
category={post.type}
title={post.title}
author={post.by}
image={post.url}
link={post.url}
/>
</li>
)}
</ul>
</div>
</>
)
};
export default Blog;