英文:
Is there a way to remove parts of arrays and add to another in ReactJS
问题
以下是翻译好的部分:
我有一组电影类型数组,还有两个数组,一个是`selectedGenres`,另一个是`genres`。我正在使用[Material UI](https://mui.com/material-ui/react-chip/)来将这些类型显示为`<Chip />`,使用`.map`函数。我试图实现这样一种情况:未选择的`genres`会显示出来,当你点击其中一个类型时,它会被发送到`selectedGenres`数组中,并从`genres`数组中删除。当我使用下面的`onClick`和`onDelete`代码时,代码没有从`genres`数组中删除点击的对象,当它被发送到`selectedGenres`中,反之亦然。这些类型是从[TMDB API](https://developer.themoviedb.org/reference/genre-movie-list)中导入的,位于`Genres.jsx`文件中。
以下是`Genres.jsx`的代码:
```jsx
import Chip from "@mui/material/Chip";
const Genres = ({
selectedGenres,
setSelectedGenres,
genres,
setGenres,
type,
setPage,
}) => {
// 添加和删除函数
const handleAdd = (genre) => {
setSelectedGenres([...selectedGenres, genre]);
setGenres(genres.filter((g) => g.id !== genre.id));
};
const handleRemove = (genre) => {
setGenres([...genres, genre]);
setSelectedGenres(
selectedGenres.filter((selected) => selected.id !== genre.id)
);
};
const fetchGenres = async () => {
const apiKey = MY_API_KEY;
const { data } = await axios.get(
`https://api.themoviedb.org/3/genre/${type}/list?api_key=${apiKey}&language=en-US`
);
setGenres(data.genres);
};
useEffect(() => {
fetchGenres();
});
return (
// 用于渲染两个芯片的React渲染函数
{selectedGenres.map((genre) => (
<Chip
sx={{ margin: "5px" }}
label={genre.name}
key={genre.id}
color="primary"
clickable
onDelete={() => handleRemove(genre)}
/>
))}
{genres.map((genre) => (
<Chip
sx={{ margin: "5px" }}
label={genre.name}
key={genre.id}
clickable
onClick={() => handleAdd(genre)}
/>
))}
)
}
以下是导入Genres.jsx
的Movies.jsx
的代码:
import Genres from "./Genres.jsx";
const Movies = () => {
const [genres, setGenres] = useState([]);
const [selectedGenres, setSelectedGenres] = useState([]);
return (
<Genres
type="movie"
selectedGenres={selectedGenres}
setSelectedGenres={setSelectedGenres}
genres={genres}
setGenres={setGenres}
setPage={setPage}
/>
)
}
我得到一个错误,它指出我有两个具有相同键的不同对象。这是问题吗?
<details>
<summary>英文:</summary>
I have a list of movie genre arrays and I have two arrays where on is the `selectedGenres` and the other is the `genres`. I am using [Material UI](https://mui.com/material-ui/react-chip/) to diplay the genres as a `<Chip />` using a `.map` function. I am trying to do something where the unselected `genres` are shown and when you click on one genre, it gets sent to the `selectedGenres` array and is deleted from the `genres` array. When I have the below code for `onClick` and `onDelete`, the code is not deleting the clicked object from the `genres` array when it is sent to `selectedGenres` and vice versa. The genres are imported from [TMDB API][1] in the `Genres.jsx` file.
**Below is the code for `Genres.jsx`**
import Chip from "@mui/material/Chip";
const Genres = ({
selectedGenres,
setSelectedGenres,
genres,
setGenres,
type,
setPage,
}) => {
// Add and Remove Function
const handleAdd = (genre) => {
setSelectedGenres([...selectedGenres, genre]);
setGenres(genres.filter((g) => g.id !== genre.id));
};
const handleRemove = (genre) => {
setGenres([...genres, genre]);
setSelectedGenres(
selectedGenres.filter((selected) => selected.id !== genre.id)
);
};
const fetchGenres = async () => {
const apiKey = MY_API_KEY;
const { data } = await axios.get(
`https://api.themoviedb.org/3/genre/${type}/list?api_key=${apiKey}&language=en-US`
);
setGenres(data.genres);
};
useEffect(() => {
fetchGenres();
});
return (
// React Render Function for Both Chips
{selectedGenres.map((genre) => (
<Chip
sx={{ margin: "5px" }}
label={genre.name}
key={genre.id}
color="primary"
clickable
onDelete={() => handleRemove(genre)}
/>
))}
{genres.map((genre) => (
<Chip
sx={{ margin: "5px" }}
label={genre.name}
key={genre.id}
clickable
onClick={() => handleAdd(genre)}
/>
))}
)
}
**Below is the code for `Movies.jsx` which imports `Genres.jsx`**
import Genres from "./Genres.jsx";
const Movies = () => {
const [genres, setGenres] = useState([]);
const [selectedGenres, setSelectedGenres] = useState([]);
return (
<Genres
type="movie"
selectedGenres={selectedGenres}
setSelectedGenres={setSelectedGenres}
genres={genres}
setGenres={setGenres}
setPage={setPage}
/>
)
}
I am getting an error which states that I have two different objects with the same key. Is that the problem?
[1]: https://developer.themoviedb.org/reference/genre-movie-list
</details>
# 答案1
**得分**: 1
你的代码中除了在Generes.js中的useEffect里忘记添加依赖列表外,一切都是正确的。
`React.useEffect(() => {
fetchGenres();
}, [])`
因此,它的行为类似于componentDidUpdate,并持续调用API并设置genres状态为所有19个项目。
从useEffect中移除依赖列表,你会看到不断触发API调用。
已在codesandbox中进行了修改,请查看,https://codesandbox.io/s/wandering-haze-3glrk6
<details>
<summary>英文:</summary>
Everything is correct in your code except you forgot to add dependency list in your useEffect inside Generes.js
` React.useEffect(() => {
fetchGenres();
}, [])`
Because of which it acted like componentDidUpdate and kept invoking the API continously and setting genres state with all 19 items.
Remove the dependency list from useEffect, you can see continuous API calls getting triggered,
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/DgWzl.png
Modified in codesandbox as well please review, https://codesandbox.io/s/wandering-haze-3glrk6
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论