#reactjs #react-hooks
#reactjs #реагирующие крючки
Вопрос:
Я запутался с крючками useEffect и useState. У меня есть страница, на которой я загружаю список фильмов, используя перехват useEffect. Список хорошо отображается на моем экране. Когда я хочу отредактировать фильм, я нажимаю на него, и это отправляет идентификатор этого фильма в метод, в котором я хочу найти фильм в списке фильмов в состоянии, загрузить этот фильм в форме и представить его для редактирования. Теперь, когда я хочу просмотреть этот фильм, список фильмов в моем состоянии пуст. Хотя это показано на моем экране. Итак, мне интересно, что тогда делают setMovies и как они отображаются на экране, но я получаю пустой массив где-либо еще?
Раньше я работал с компонентами класса, где это не было проблемой.
import React, { useState, useEffect } from 'react';
const MovieList = () => {
const [openEdit, setOpenEdit] = useState(false);
const [movieToEdit, setMovieToEdit] = useState({});
const [movies, setMovies] = useState([]);
const openEditMovie = (movieId) => {
console.log("movies", movies); // is empty here !?
setMovieToEdit(movies.find(m => m.id === movieId));
setOpenEdit(true);
}
useEffect(() => {
fetchMovies();
}, []);
const fetchMovies = async () => {
let movies = await axios.get('/movies'); // just sample code, you get the picture
console.log("movies", movies); // lists movies
setMovies(movies);
}
return (
<List source={movies}/>
{ /* and the dialog with the form etc go below here */ }
);
};
export default MovieList;
Комментарии:
1. Я сомневаюсь в именах переменных, можете ли вы изменить переменную movie на что-то другое?
2. Может быть, стоит прочитать -> reactjs.org/docs/hooks-reference.html amp; reactjs.org/docs/hooks-intro.html
3. @danialdehvan Мне трудно найти вызываемую переменную
movie
..
Ответ №1:
Вот небольшой макет вашего кода, который, похоже, делает то, что ожидалось, поэтому я бы проверил возвращаемое значение вашего axios-вызова. Можете ли вы уточнить, отображается ли ваш журнал в функции [object Object]
fetchMovie? Я спрашиваю, поскольку вы упомянули, что на самом деле в нем перечислены фильмы..
import React, { useState, useEffect} from 'react';
const MovieList = () => {
const [openEdit, setOpenEdit] = useState(false);
const [movieToEdit, setMovieToEdit] = useState({});
const [movies, setMovies] = useState([]);
const openEditMovie = (movieId) => {
console.log("movieLogEdit:",movies); // not empty
setMovieToEdit(movies.find(m => m.id === movieId));
setOpenEdit(true);
}
useEffect(() => {
fetchMovies();
}, []);
const fetchMovies = async () => {
let movies = [1,2,4]; // mocked data
console.log("movieLogFetch:" movies); // lists movies on initial render since useEffect has [] as second argument
setMovies(movies);
}
return (
<div>
<button className="button is-primary" onClick={openEditMovie}>
Open Movie Editor
</button>
</div>
);
};
export default MovieList;
Ответ №2:
Ваш код кажется прекрасным. Просто измените setMovies(movies)
на setMovies(movies.data)
, потому что Axios возвращает объект ответа со свойством data
, которое содержит данные, отправленные сервером (API).
const fetchMovies = async () => {
let movies = await axios.get("/movies");
console.log("movies", movies.data);
setMovies(movies.data);
};
Комментарии:
1. Спасибо за комментарий. Я понимаю вашу точку зрения, но вызов axios был просто псевдокодом. Однако я дважды проверю возвращаемое значение.
Ответ №3:
Ответ был найден, и я понимаю, что, упростив свой код, я упустил ту часть, которая вызвала проблему. В этом fetchMovies
методе я создавал массив значений для передачи в таблицу данных пользовательского интерфейса Material (https://www.material-ui-datatables.com ).
const fetchMovies = async () => {
let movies = await axios.get('/movies'); // just sample code, you get the picture
console.log("movies", movies); // lists movies
setMovies(
movies.map(movie => [
movie.id,
movie.name,
movie.year,
<EditIcon onClick={() => openEditMovie(movie.id)}/>
])
);
}
Теперь, по-видимому, как мне сказали, во время создания этого массива openEditMovie
функция копируется в память вместе с состоянием, каким оно было в тот момент. Поэтому при вызове метода из onClick
, у меня всегда будет доступно старое состояние с пустым массивом movies.
Когда вы позже вызываете openEditMovie
где-то еще из кода, у меня есть доступ к обновленному состоянию.
Никогда не видел, что это произойдет!