#javascript #reactjs
Вопрос:
Я пытаюсь реализовать небольшое приложение с loadMore
кнопкой.
По умолчанию он должен выводить 3 данных и показывать еще 3 данных каждый раз, когда пользователь нажимает кнопку загрузить больше.
Попробовав несколько способов, я пришел к этому решению, предложенному в этой статье.
Вот ссылка codesandox
App.js
let arrayForHoldingStories = [];
const [topStoryIds] = useStories();
const [storiesToShow, setStoriesToShow] = useState([]);
const [next, setNext] = useState(3);
const loopWithSlice = (start, end) => {
const slicedStories = topStoryIds.slice(start, end);
arrayForHoldingStories = [...arrayForHoldingStories, ...slicedStories];
setStoriesToShow([...arrayForHoldingStories, ...slicedStories]);
};
useEffect(() => {
loopWithSlice(0, storiesPerPage);
}, [topStoryIds]);
const handleShowMorePosts = () => {
let loadedMore = next storiesPerPage;
loopWithSlice(next, loadedMore);
setNext(next storiesPerPage);
};
Но проблема в том, что при объединении исходного массива и нового массива у них одинаковые элементы, и это приводит к ошибке
Warning: Encountered two children with the same key, `26991887`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
Я попытался удалить дубликаты из обоих массивов с помощью forEach
set
функций или перед объединением, но это тоже не сработало.
Моя попытка
const loopWithSlice = (start, end) => {
const slicedStories = topStoryIds.slice(start, end);
arrayForHoldingStories = [...arrayForHoldingStories, ...slicedStories];
setStoriesToShow([...arrayForHoldingStories, ...slicedStories]); //it throws mentioned error
/* slicedStories.forEach((uniqueId) => { //this will also throw same error
arrayForHoldingStories.forEach((addedId) => {
if (uniqueId !== addedId) {
setStoriesToShow([...slicedStories, ...arrayForHoldingStories]);
}
});
}); */
/* setStoriesToShow([ //this will also throw same error
...new Set([...arrayForHoldingStories, ...slicedStories])
]); */
};
Любая помощь будет оценена по достоинству.
Ответ №1:
Согласно вашему описанию, вам не нужно иметь аргументы конца или начала для вашего цикла с функцией среза. Вы можете использовать длину storiesToShow
состояния
import React, { useState, useEffect } from "react";
import Stories from "./Stories";
import useStories from "./hooks/useStories";
function App() {
const storiesPerPage = 3;
let arrayForHoldingStories = [];
const [topStoryIds] = useStories();
const [storiesToShow, setStoriesToShow] = useState([]);
const [next, setNext] = useState(3);
const loopWithSlice = () => {
const toShow = topStoryIds.slice(
storiesToShow.length,
storiesToShow.length storiesPerPage
);
setStoriesToShow([...storiesToShow, ...toShow]);
};
useEffect(() => {
if (topStoryIds) {
loopWithSlice();
}
}, [topStoryIds]);
const handleShowMorePosts = () => {
let loadedMore = next storiesPerPage;
loopWithSlice(next, loadedMore);
setNext(next storiesPerPage);
};
console.log("next", next);
console.log("storiesPerPage", storiesPerPage);
console.log("loopWithSlice", loopWithSlice);
console.log("arrayForHoldingStories", arrayForHoldingStories);
console.log("storiesToShow", storiesToShow);
return (
<>
<div>
{storiesToShow.length > 0 amp;amp;
storiesToShow.map((storyId) => (
<Stories storyId={storyId} key={storyId} />
))}
</div>
<button onClick={handleShowMorePosts}>load more</button>
</>
);
}
export default App;
Вы можете проверить sanbox здесь для получения полного кода.
Комментарии:
1. Привет @Джош, большое тебе спасибо. В этом есть большой смысл.
2. Привет @Josh, еще раз спасибо за ответ. Не могли бы вы, пожалуйста, ответить еще на один вопрос? Несмотря на то, что ваше решение работает нормально, и это незначительная вещь, но я хотел бы понять и решить предупреждение useEffect, в котором говорится: У React Hook useEffect отсутствует зависимость: «loopWithSlice». Либо включите его, либо удалите массив зависимостей. (реагирующие крючки/исчерпывающие депы)eslint» . Если я удалю массив зависимостей, приложение выйдет из строя. Каким было бы лучшее решение, чтобы избавиться от этого предупреждения? Заранее благодарю
3. @Greg это связано с вызовом
loopWithSlice
начального рендеринга, который создает своего рода шаблон подписки дляuseEffect
. ТакжеloopWithSlice
функция может меняться между визуализациями, поэтому это правило гарантирует, что функция будет включена в массив deps в случае ее изменения. Я изменил песочницу, чтобы показать лучший способ без вызоваloopWithSlice
начального рендеринга.4. Привет @Josh, еще раз спасибо за вашу помощь. Я понял.