I am making a component in React to paginate questions. The questions come from different components (representing tests with questions). Some of these questions are answered with checkbox or radiobutton. I give an example so that the error can be seen: I have a collection of questions in an array (within a "Test" component), and we pass it to the "Pagination" component. Here we see the example array with multiple choice questions with 2 example checkboxes, and how we pass it to the "Pagianacion" Component:
const dataTest = [
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 1</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 2</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 3</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 4</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 5</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 6</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 7</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 8</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>,
<><div className="row"><div className="col-12 col-md-9 col-lg-10 col-xl-10 col-xxl-10"><span>Question 9</span></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-1" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-1">Yes</label></div></div><div className="col-3 col-md-1 col-lg-1 col-xl-1"><div className="form-check"><input id="formCheck-2" className="form-check-input" type="checkbox" /><label className="form-check-label" for="formCheck-2">No</label></div></div></div></>
]
return (
<>
<Paginacion elementsList={dataTest} currentPagePar={0} rangePagesPar={5} /> <-- We write 5 elements per page. And we pass the array of elements "dataTest". The default page is "0" in this example.
data
</>
)
Next here I show the "Pagination" component. We see that in the piece of code " fullList.slice" it selects the segment of the array that I want to display with a simple calculation:
export const Paginacion = ({elementsList, currentPagePar, rangePagesPar}) => {
const [fullList, setFullList] = useState(elementsList)
const [currentList, setCurrentList] = useState([])
const [currentPage, setCurrentPage] = useState(currentPagePar)
const [rangePages, setRangePages] = useState(rangePagesPar) //10 items per page.
const changePage = (page) => {
setCurrentPage (page);
}
useEffect(() =>{
console.log ( currentPage * rangePages);
console.log ((currentPage * rangePages) rangePages);
/*
let dat = [];
for (let i = index; i < (index rangePages) && i < fullList.length; i ){
dat.push(fullList[i]);
}
console.log (dat);
setCurrentList(dat);
*/
}, [,currentPage]);
return (
<>
{
//Calculate init index (it depends ont the current page) to show the questions, and the number of elements to show (its rangePages) <---- LINE SHOWS HTML ELEMENTS
fullList.slice(currentPage * rangePages, (currentPage * rangePages) rangePages).map((current) => (
<>
{current}
</>
))
}
<nav>
<ul className="pagination">
{
(() => {
//Draw pages numbers.
let valD = fullList.length;
let totalPages = valD / rangePages;
if (valD%rangePages !=0) totalPages = 1;
const retArray = [];
retArray.push(<li key={"\"init\""} className="page-item"><a className="page-link" aria-label="Previous" href="#"><span aria-hidden="true">«</span></a></li>);
if (valD%rangePages !=0) totalPages = 1;
for (let index = 0; index < totalPages; index ){
retArray.push(
<li key={index} className="page-item"><a className="page-link" href="#" onClick={() => changePage(index)}>{index}</a></li>
);
}
retArray.push(<li key={"\"end\""} className="page-item"><a className="page-link" aria-label="Next" href="#"><span aria-hidden="true">»</span></a></li>);
return retArray;
}
)()
}
</ul>
</nav>
</>
)
}
The problem: when I change the page to show other questions, the text of the question is changed correctly, but the results that the user has entered in the checkbox (example) or in the radiobuttons DO NOT change to the new value, the ones that were there are kept on the previous page. In the images I show the error:
- The questions on page 1 are displayed.
- I make changes to the checkboxes of the questions on page 1.
- Page change and the texts of the questions on that page are displayed correctly, but the results displayed are those of the questions on page 1. The questions on page 2 are not displayed! I attach the screenshots. What am I doing wrong?
---------------- EDIT ------------ I change this part:
//Calculate init index (it depends ont the current page) to show the questions, and the number of elements to show (its rangePages)
fullList.slice(currentPage * rangePages, (currentPage * rangePages) rangePages).map((current, i) => (
<>
<li key={(currentPage * rangePages) i}>
{current}
</li>
</>
))
The problem may be here, in the unique keys as the first answer comment says. Now it seems that the IDs are simply not generated correctly, because when changing the page the values are simply deleted.
CodePudding user response:
Noticing a few issues, whenever mapping or looping through something and rendering JSX, you need to add a unique string key like so:
{
fullList.slice(currentPage * rangePages, (currentPage * rangePages)
rangePages).map((current, i) => (
<React.Fragment key={current.id}> // Required by React's diffing algo, should not use index if order will change.
{current}
</React.Fragment>
))
}
Relevant docs: https://reactjs.org/docs/lists-and-keys.html#keys
It's also not a good idea to set state from props, instead you can pass the state and method to set the state as props down to your component. For example:
// No need to set props as state, pass these down from parent component.
const [fullList, setFullList] = useState(elementsList)