Javascript-форум (https://javascript.ru/forum/)
-   Библиотеки/Тулкиты/Фреймворки (https://javascript.ru/forum/library-toolkit-framework/)
-   -   React нужна помощь (https://javascript.ru/forum/library-toolkit-framework/81247-react-nuzhna-pomoshh.html)

dewembas 29.10.2020 00:35

React нужна помощь
 
Всем привет, мне нужна помощь, есть проект с постерами фильмов, пр нажатии на постер нужно что бы его бэкграунд был изображением постера, но я запутался, не могу понять как сделать что бы к конкретному постеру открывался тот же постер, они у меня открываются все по очереди как сделать открытие по индексу или что то подобное , буду очень благодарен за помощь.
Ссылка на репозиторий : https://github.com/Dewembas/React-moviees

Nexus 29.10.2020 02:00

Научитесь форматировать свой код.

Как я понял речь о компоненте Movie.
У вас на каждый фильм рендерится по одной картинке и по изначально скрытому модальному окну.
Видимость всех модалок у вас зависит от одной переменной - «show».

Во-первых, имхо, на каждый элемент необязательно рендерить по модальному окно, можно обойтись вторым.
Во-вторых, при нажатии на любой постер фильма открываются сразу все модальные окна.

Сохраняйте в state не состояние модалки (открыт/закрыт), а индекс открытого окна.
Если у вас как и сейчас останется на каждый фильм по окну, то просто проверяете, что индекс текущего элемента равен "индексу открытого фильма".
Если оставите только одно окно, что правильнее, то просто проверяете, что у вас есть открытый элемент. В этом случае получить сам элемент можно по его известному индексу.

Nexus 29.10.2020 02:06

Примерно так:

function Movies() {
    const [items, saveItems] = useState([]);
    const [openItemIndex, saveOpenItemIndex] = useState(null);
    
    return <>
        {items.map((item, index) => (
            <div>
                <img src={item.poster_src} onClick={() => saveOpenItemIndex(index)} />
            </div>
        ))}
        
        <Modal show={Boolean(openItemIndex)} />
    </>;
}

dewembas 30.10.2020 11:34

Цитата:

Сообщение от Nexus (Сообщение 530176)
Научитесь форматировать свой код.

Как я понял речь о компоненте Movie.
У вас на каждый фильм рендерится по одной картинке и по изначально скрытому модальному окну.
Видимость всех модалок у вас зависит от одной переменной - «show».

Во-первых, имхо, на каждый элемент необязательно рендерить по модальному окно, можно обойтись вторым.
Во-вторых, при нажатии на любой постер фильма открываются сразу все модальные окна.

Сохраняйте в state не состояние модалки (открыт/закрыт), а индекс открытого окна.
Если у вас как и сейчас останется на каждый фильм по окну, то просто проверяете, что индекс текущего элемента равен "индексу открытого фильма".
Если оставите только одно окно, что правильнее, то просто проверяете, что у вас есть открытый элемент. В этом случае получить сам элемент можно по его известному индексу.

Подскажите пожалуйста еще , как сделать одно модальное окно? Как упоминалось выше

Nexus 30.10.2020 13:05

Цитата:

Сообщение от dewembas
как сделать одно модальное окно?

:-? https://javascript.ru/forum/library-...tml#post530177

dewembas 30.10.2020 14:32

Цитата:

Сообщение от Nexus (Сообщение 530216)

Упс, спасибо

dewembas 31.10.2020 00:59

Цитата:

Сообщение от Nexus (Сообщение 530216)

У меня опять вопрос :( не пойму , а как же сделать бэкграунд я уже вроде все попробовал он пишет undefined, что делать ?:help:

Nexus 31.10.2020 01:10

dewembas, сделайте макет вашей задачи в любой песочнице, без него непонятно где у вас undefined.

dewembas 31.10.2020 02:31

Вложений: 1
Цитата:

Сообщение от Nexus (Сообщение 530261)
dewembas, сделайте макет вашей задачи в любой песочнице, без него непонятно где у вас undefined.

Не получается создать в песочнеце, фетч запрос не хочет обрабатываться
могу только вот скрин прислать где undefined

Nexus 31.10.2020 14:10

dewembas, если ни вы, ни ваш редактор кода форматировать этот самый код не умеете, то можете воспользоваться этим ресурсом: https://prettier.io/playground

В моем примере константы items и saveItems были аналогом ваших переменных data и setData.
Что лежит в константе data без просмотра кода сказать сложно, там может быть что угодно, однако константа items наверняка хранит итерируймый объект и почти наверняка это массив.
Так что либо удалите мою версию, либо исправьте свою.

Ваши константы handleClose и handleShow можете удалить, они лишние как и show вместе с setShow.

39-я строка вашего неформатированного кода: лишний третий аргумент callback'а, переданного в метод map. Он, как я и написал, лишний, к тому же имеет название, которое вводит в заблуждение (useState). Если интересно, что передается третьим аргементом в метод map - смотрите тут.

В 40-й строке замените атрибут onClick на этот:
onClick={() => saveOpenItemIndex(index)}


50-я и 51-я строки должны быть такими:
show={!!openItemIndex}
onHide={() => saveOpenItemIndex(null)}


Строки 45 и 64 - лишние.

В 55-й строке вместо «data?.poster_path» должно быть «data[openItemIndex]?.poster_path».

Вы, похоже, совсем не пытаетесь вникнуть в то, что пишите.

dewembas 31.10.2020 17:24

Огромное спасибо, буду улучшать знания для того что бы больше вникать :)

dewembas 03.11.2020 02:48

Цитата:

Сообщение от Nexus (Сообщение 530261)
dewembas, сделайте макет вашей задачи в любой песочнице, без него непонятно где у вас undefined.

Попрошу у вас ещё подсказку) если не затруднит, подскажите как по онклику на кнопку добавить в избранное, переместить данный фильм на страницу избранного ? Буду благодарен за любую подсказку .:-?

Nexus 03.11.2020 11:57

dewembas,
Цитата:

Сообщение от dewembas
как по онклику на кнопку добавить в избранное, переместить данный фильм на страницу избранного ?

По-хорошему стоит реализовать регистрацию/авторизацию пользователей и сохранить список избранного в БД.

Но чтобы просто "поиграться", список избранного можно хранить в localStorage либо в indexedDB.

Если решите хранить список в IndexedDB, то лучше установите пакет, который поможет с нею взаимодействовать, например LocalForage.

Работать с localStorage можно напрямую, через его API, однако для этого все же лучше написать какую-нибудь, хотя бы самую простую обертку с методами get, set для более просто модифицирования кода в будущем (к слову, LocalForage умеет работать и с localStorage в кач-ве хранилища).

Операции чтения/записи из хранилища лучше делать асинхронными, даже если они выполняются синхронно (как в случае с localStorage), чтобы потом можно было легко изменить хранилище даже на то, операции чтения/записи в которое осуществляются асинхронно.

Если вместе с "меткой" о добавлении фильма в избранное нужно хранить еще какие-либо данные, например дату добавления этого фильма в избранное, то лучше (имхо, лучше для того юзать БД) хранить список избранного не как одну запись со списком идентификаторов в хранилище, а как список ключ-значение (<prefix>-<movie-id> => <some-details>). Т.е. для каждого отдельного фильма добавленного в хранилище создавать ключ в определенном формате (пример формата был выше), значением которого будет дополнительная информация об этом ключе.

dewembas 06.11.2020 03:39

Цитата:

Сообщение от Nexus (Сообщение 530333)
dewembas,
По-хорошему стоит реализовать регистрацию/авторизацию пользователей и сохранить список избранного в БД.

Но чтобы просто "поиграться", список избранного можно хранить в localStorage либо в indexedDB.

Если решите хранить список в IndexedDB, то лучше установите пакет, который поможет с нею взаимодействовать, например LocalForage.

Работать с localStorage можно напрямую, через его API, однако для этого все же лучше написать какую-нибудь, хотя бы самую простую обертку с методами get, set для более просто модифицирования кода в будущем (к слову, LocalForage умеет работать и с localStorage в кач-ве хранилища).

Операции чтения/записи из хранилища лучше делать асинхронными, даже если они выполняются синхронно (как в случае с localStorage), чтобы потом можно было легко изменить хранилище даже на то, операции чтения/записи в которое осуществляются асинхронно.

Если вместе с "меткой" о добавлении фильма в избранное нужно хранить еще какие-либо данные, например дату добавления этого фильма в избранное, то лучше (имхо, лучше для того юзать БД) хранить список избранного не как одну запись со списком идентификаторов в хранилище, а как список ключ-значение (<prefix>-<movie-id> => <some-details>). Т.е. для каждого отдельного фильма добавленного в хранилище создавать ключ в определенном формате (пример формата был выше), значением которого будет дополнительная информация об этом ключе.


Спасибо, решил все таки использовать LocslStorage, но есть опять проблема в масив пушится только один объект, что делать ?

Nexus 06.11.2020 11:21

Записывайте в хранилище не сами объекты, а их идентификаторы.
Локальное хранилище не резиновое, записывая в него объекты вы быстро израсходуете все доступное пространство.

Цитата:

Сообщение от dewembas
Работать с localStorage можно напрямую, через его API, однако для этого все же лучше написать какую-нибудь, хотя бы самую простую обертку с методами get, set

Мой совет по поводу обертки для localStorage вы проигнорировали, ваше право.

Цитата:

Сообщение от dewembas
но есть опять проблема в масив пушится только один объект

Вы записываете в хранилище всегда только один объект, чему тут удивляться?

const favotireMoviesIds = JSON.parse(localStorage.getItem('favorite-movies')) || [];
const markMovieAsFavorite = movieId => {
    localStorage.setItem('favorite-movies', JSON.stringify([...favotireMoviesIds, movieId]));
};

dewembas 13.12.2020 03:17

И вновь здравствуйте, вот опять вернулся к этому проекту, уже второй день нее могу сделать проверку LocalStorage на то что бы фильм добавлялся только один раз, прошу помощи :cray:
Буду признателен , за прошлый ответ большое спасибо, немного забыл поблагодарить :-?
Ссылка на саму страницу где нужно совершить проверку : https://github.com/Dewembas/React-mo...ents/Modals.js

voraa 13.12.2020 07:55

Если бы Вы еще намекнули, какую структуру имеет arr, что такое objLocal, и что делает markMovieAsFavorite (какие у нее параметры)

dewembas 13.12.2020 20:25

Цитата:

Сообщение от voraa (Сообщение 531643)
Если бы Вы еще намекнули, какую структуру имеет arr, что такое objLocal, и что делает markMovieAsFavorite (какие у нее параметры)

const arr=JSON.parse(localStorage.getItem('favorite-movies'))
let objLocal ={
  img: data[openItemIndex]?.poster_path,
  title: data[openItemIndex]?.original_title,
  opis:  data[openItemIndex]?.overview,
  id: data[openItemIndex]?.id,
  language: data[openItemIndex]?.original_language,
  date: data[openItemIndex]?.release_date,
  score: data[openItemIndex]?.vote_average,
}

const favotireMoviesIds = JSON.parse(localStorage.getItem('favorite-movies')) || [];
    const markMovieAsFavorite = movieId => {
    localStorage.setItem('favorite-movies', JSON.stringify([...favotireMoviesIds, movieId]));
};

Вот.

voraa 13.12.2020 21:16

Тогда вот это совсем непонятно

45 else if (arr[objLocal]?.id!==data[openItemIndex]?.id){
markMovieAsFavorite(objLocal)
console.log("dob")
}
Как я понимаю, надо узнать, содержится ли в arr (вернее узнать, что не содержится) объект с id: data[openItemIndex]?.id. Так?
Тогда
if (! arr.find(el => el.id == data[openItemIndex].id) ) {

И это непонятно.
markMovieAsFavorite(undefined)
Зачем туда запихивать лишний элемент undefined? И потом везде таскать ?.

Ну напишите вы чуть больше кода

const markMovieAsFavorite = movieId => {
const a = [...favotireMoviesIds]
if (movieId) a.push(movieId)
localStorage.setItem('favorite-movies', JSON.stringify(a));
}

А какой смысл хранить в localStorage все структуры вместе с текстовыми описаниями? Одних индексов не достаточно? По ним же всегда можно найти нужный объект.

dewembas 14.12.2020 01:44

Большое спасибо, сделал немного по другому , без проверок, просто кнопку меняю через тернарный оператор, с помощью перебора массива который вы написали, ещё раз спасибо


Часовой пояс GMT +3, время: 08:14.