简体   繁体   English

如何修复在分页上持续存在的 State?

[英]How to fix State that is persisting on pagination?

Hello beautiful people!你好美丽的人们!

I'm building a MERN stack website and having a problem with this Edit Mode state:我正在构建一个 MERN 堆栈网站,但此编辑模式 state 存在问题:

在此处输入图像描述

  • When I click on the Edit button , it will set the Edit mode to true and display the input field.当我点击Edit button时,它会将Edit 模式设置为true并显示输入字段。

  • I click on the Edit button again to set the Edit mode to false and hide the input field.我再次单击编辑按钮编辑模式设置为false并隐藏输入字段。

  • But if I don't change the Edit mode 's state to false and go to the next page - The input field will display on the same row number on the next page but cleared out the previous input.但是,如果我不将Edit mode的 state 更改为false并将 go 更改为下一页 - 输入字段将显示在下一页的相同行号上,但清除了先前的输入。

  • The Update (Checkmark) button and other buttons in the rows work fine行中的更新(复选标记)按钮和其他按钮工作正常

-> How to reset the state and/or make the Edit button automatically hide when we move to other page? -> 当我们移动到其他页面时,如何重置 state 和/或使编辑按钮自动隐藏?



Here's my code:这是我的代码:

- Pagination: - 分页:

export default function Pagination({ foodPerPage, totalFood, paginate, currentPage }) {
    const pageNumbers = []

    for (let i = 1; i <= Math.ceil(totalFood / foodPerPage); i++) {
        pageNumbers.push(i)
    }
    return (
    <nav aria-label="Pagination" className="pagination">
        <ul>
            {pageNumbers.map(number => (
                <li key={number} className="page-item">
                    <button 
                        className={(currentPage === number ? "page-link active" : "page-link")}
                        onClick={() => paginate(number)}
                    >
                        {number}
                    </button>
                </li>
            ))}
        </ul>
    </nav>
  );
}

- App.js - 应用程序.js

export default function DinnerIdeas() {
    const [foodList, setFoodList] = useState([])

    const [searchedFood, setSearchedFood] = useState([])
    const [noResult, setNoResult] = useState(false)

    
    
    // Display food list:
    useEffect(() => {
      let unmounted = false
      Axios.get("https://my-project.herokuapp.com/read")
      .then((response) => {
        if (!unmounted) {
          setFoodList(response.data)
        }
      })
      .catch(error => {
        console.log(`The error is: ${error}`)
        return
      })
      return () => {
        unmounted = true
      }
    }, [foodList])
    


      // Paginate states:
      const [currentPage, setCurrentPage] = useState(1)
      const [foodPerPage] = useState(5)
      
      // Get current food:
      const indexOfLastFood = currentPage * foodPerPage
      const indexOfFirstFood = indexOfLastFood - foodPerPage
      const currentFood = foodList.slice(indexOfFirstFood, indexOfLastFood)
      const currentSearchedFood = searchedFood.slice(indexOfFirstFood, indexOfLastFood)
      
      const paginate = (pageNumber) => {
        setCurrentPage(pageNumber)
      }
    
    return (
      <section>
        {noResult ? <ResultNotFound/>
          :
            <FoodListTable
              foodList={foodList}
              currentFood={currentFood}
              searchedFood={searchedFood}
              currentSearchedFood={currentSearchedFood}
              totalFood={foodList.length}
              totalSearchedFood={searchedFood.length}
              currentPage={currentPage}
              paginate={paginate}
              noResult={noResult}
              foodPerPage={foodPerPage}
            />
        }
      </section>
    )
  }

- FoodListTable.js - FoodListTable.js

import FoodListRow from './FoodListRow'
import Pagination from "../Pagination"


export default function FoodListTable(props) {
    return (
        <div className="flist container">
            <table>
                <thead>
                    <tr>
                        <th>
                            Food name
                        </th>
                        <th>Price</th>
                        <th>
                            Action
                        </th>
                    </tr>
                </thead>
                <tbody>
                    {props.searchedFood.length > 0 ? props.currentSearchedFood.map((val, key) => {
                        return (
                            <FoodListRow
                                val={val}
                                key={key} 
                                foodName={val.foodName}
                                isVegetarian={val.isVegetarian}
                                priceRange={val.priceRange}
                                foodUrl={val.foodUrl}
                            />    
                        )
                    }) : props.currentFood.map((val, key) => {
                        return (
                            <FoodListRow
                                val={val}
                                key={key}
                                foodName={val.foodName}
                                isVegetarian={val.isVegetarian}
                                priceRange={val.priceRange}
                                foodUrl={val.foodUrl}
                            />
                        )
                        })
                    }
                </tbody>
            </table>
            {props.searchedFood.length > 0 ? 
                <Pagination foodPerPage={props.foodPerPage} totalFood={props.totalSearchedFood} paginate={props.paginate} currentPage={props.currentPage} />
                :<Pagination foodPerPage={props.foodPerPage} totalFood={props.totalFood} paginate={props.paginate} currentPage={props.currentPage} />
            }
        </div>
    )
}

- FoodListRow Component inside <FoodListTable/> - <FoodListTable/>内的 FoodListRow 组件

export default function FoodListRow(props) {
    // Edit mode:
    const [editBtn, setEditBtn] = useState(false)

    const handleEdit = () => {
        setEditBtn(!editBtn)
    }

    return (
        <tr key={props.val._id}>
            <td>
                {props.val.foodName}
                // Display the input field on Edit mode:
                {editBtn && 
                    <div>
                        <input
                            type="text"
                            name="edit"
                            placeholder="New food name.."
                            autoComplete="off"
                            onChange={(event) => {setNewFoodName(event.target.value)}}
                        />
                        <button
                        onClick={() => updateFoodName(props.val._id)}
                        >
                            ✓
                        </button> 
                    </div>
                }
            </td>
            <td>{props.val.priceRange}</td>
            <td>
                <a 
                    href={props.val.foodUrl} 
                    className="flist__table--btn"
                    target="_blank"
                    rel="noopener noreferrer" 
                >
                    🔗
                </a>
                <button 
                    onClick={handleEdit}
                >
                    ✏️
                </button>
                <button 
                    onClick={() => deleteFood(props.val._id)}
                >
                    ❌
                </button>
            </td>
        </tr>
    );

Error must be on the code you've not share: FoodListTable You probably map to render your FoodListRow using the map index as a key .错误必须出现在您未共享的代码上: FoodListTable您可能FoodListRow使用 map 索引作为key来呈现您的 FoodListRow。

SO when you change your page from Pagintion, the key stays the same across render and your inner state is not changed.因此,当您从 Pagintion 更改页面时, key在整个渲染过程中保持不变,并且您的内部 state 不会更改。

So either use something else as key for FoodListRow (for exemple a database ID) or include your current page pagination in your key因此,要么使用其他东西作为FoodListRow的键(例如数据库 ID),要么在键中包含当前页面分页

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM