Я продолжаю получать пустой элемент списка аватаров, когда я нажимаю «Добавить» в первый раз, а затем после этого соответствующий элемент отображается после второго щелчка. Если я добавлю новый URL-адрес и щелкну третий раз, элемент не появится до четвертого щелчка. Скорее всего, я делаю что-то не так со своими значениями useEffect
и состояния.
import React, { useState, useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import AvatarListItem from './AvatarListItem';
import AddIcon from '@material-ui/icons/Add';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import axios from 'axios';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'column',
flexWrap: 'wrap',
backgroundColor: theme.palette.background.paper,
},
inline: {
display: 'inline',
},
formControl: {
width: '100%',
margin: theme.spacing(1),
marginBottom: '50px',
minWidth: 120,
},
extendedIcon: {
margin: '10px',
marginRight: theme.spacing(1),
},
}));
export default function AvatarList() {
const classes = useStyles();
const [url, setUrl] = useState('');
const [itemDetails, setItemDetails] = useState({});
const [items, setItems] = useState([]);
const [search, setSearch] = useState('');
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://127.0.0.1:5000/api/resources/products?url=${url}`,
)
setItemDetails(result.data[0]);
}
fetchData()
}, [search])
const addItem = (itemDetails) => {
const newItems = [...items, itemDetails];
setItems(newItems);
};
let handleSubmit = (e) => {
e.preventDefault();
console.info(itemDetails);
addItem(itemDetails);
};
let removeItem = (index) => {
const newItems = [...items];
newItems.splice(index, 1);
setItems(newItems);
};
return (
<div>
<form className = {classes.formControl} onSubmit = {e => handleSubmit(e)}>
<TextField id = "outlined-basic" label = "Amazon Url" variant = "outlined" name='newItem' onChange = {e => setUrl(e.target.value)} value = {url} />
<Button variant = "contained" color = "primary" type = "submit" value = "Submit" onClick = {() => setSearch(url)}>
<AddIcon className = {classes.extendedIcon} />
</Button>
</form>
<List className = {classes.root}>
{items.map((item, index) => (
<>
<AvatarListItem
itemDetails = {item}
key = {index}
index = {index}
removeItem = {removeItem}
/>
<Divider variant = "middle" component = "li" />
</>
))}
</List>
</div >
);
}
я хотел бы получать данные каждый раз, когда пользователь нажимает кнопку добавления, и добавлять эти данные в список элементов
Лучшим подходом может быть использование исключительно обратного вызова onSubmit
вместо использования useEffect, который может запускаться чаще, чем необходимо. Кроме того, не похоже, что вам вообще нужно использовать состояние search
или itemDetails
.
import React, { useState, useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import AvatarListItem from './AvatarListItem';
import AddIcon from '@material-ui/icons/Add';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import axios from 'axios';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'column',
flexWrap: 'wrap',
backgroundColor: theme.palette.background.paper,
},
inline: {
display: 'inline',
},
formControl: {
width: '100%',
margin: theme.spacing(1),
marginBottom: '50px',
minWidth: 120,
},
extendedIcon: {
margin: '10px',
marginRight: theme.spacing(1),
},
}));
export default function AvatarList() {
const classes = useStyles();
const [url, setUrl] = useState('');
const [items, setItems] = useState([]);
const addItem = (itemDetails) => {
const newItems = [...items, itemDetails];
setItems(newItems);
};
let handleSubmit = async (e) => {
e.preventDefault();
const result = await axios(
`http://127.0.0.1:5000/api/resources/products?url=${url}`,
)
addItem(result.data[0]);
};
let removeItem = (index) => {
const newItems = [...items];
newItems.splice(index, 1);
setItems(newItems);
};
return (
<div>
<form className = {classes.formControl} onSubmit = {handleSubmit}>
<TextField id = "outlined-basic" label = "Amazon Url" variant = "outlined" name='newItem' onChange = {e => setUrl(e.target.value)} value = {url} />
<Button variant = "contained" color = "primary" type = "submit">
<AddIcon className = {classes.extendedIcon} />
</Button>
</form>
<List className = {classes.root}>
{items.map((item, index) => (
<React.Fragment key = {index}>
<AvatarListItem
itemDetails = {item}
key = {index}
index = {index}
removeItem = {removeItem}
/>
<Divider variant = "middle" component = "li" />
</React.Fragment>
))}
</List>
</div >
);
}
если вы намерены получать данные каждый раз, когда пользователь нажимает submit
, основываясь на вашем useEffect
, вы должны основывать свой useEffect
не на search
, а на самом items
(например, когда пользователь отправляет, вы добавляете что-то к items
)
ваш код должен выглядеть так
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://127.0.0.1:5000/api/resources/products?url=${url}`,
)
setItemDetails(result.data[0]);
}
fetchData()
}, [items])
Вы проверили свой useEffect? он получает новые данные только при изменении значения
search
. это ваше намерение? или вы хотите получать данные для каждого изменения значенияitem
?