Пагинация React Redux

В первом случае: я делаю простую разбивку на страницы на стороне сервера в rails и использую реакцию в качестве внешнего интерфейса и редукцию в качестве управления состоянием. Я сделал все, и последнее, что осталось, это просто передать новый сгенерированный URL-адрес и получить новые данные. Эти данные будут получены в другом компоненте, который будет генерировать продукты. поскольку в моем случае я использую избыточность, как я могу передать эти данные моему действию по выборке данных?

Во втором случае: я попытался передать параметр с именем url и снова отправить действие выборки с данными URL, которые я ему дал. но возврат в том, что диспетчеризация не является функцией. Могу ли я даже повторно запустить действия в action.jsx?

action.jsx
    
    export const handlePage = (e, { activePage }) => {
        let pageNum = activePage
        let pageString = pageNum.toString();
        let url = "/api/v1/products/index/?page=" + pageString; ------> Use This ...
    }
    

export const fetchProducts = (url) => { ------> In Here
        return (dispatch) => {
            console.log(url);
            dispatch(fetchProductsRequest());
            axios
              .get(url) 
              .then((response) => {
                // response.data is the products
                const products = response.data.products;
                dispatch(fetchProductsSuccess(products));
              })
              .catch((error) => {
                // error.message is the error message
                dispatch(fetchProductsFailure(error.message));
              });
        };
    };

    export class Paginator extends React.Component {
      state = {
        page: [],
        pages: [],
      };
    
    
      componentDidMount() {
        axios
          .get("/api/v1/products/index", { withCredentials: true })
          .then((response) => {
            this.setState({
              page: response.data.page,
              pages: response.data.pages,
            });
          })
          .catch((error) => {
            console.log("Check Login Error", error);
          });
      }
    
      render() {
        return (
          <div>
            <Pagination count={this.state.pages} page={this.state.page} onChange={handlePage} />
          </div>
        );
      }
    }

Продукт.jsx

import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import "../../style/frequentlyasked.scss";
import ItemOne from "../../files/Item-One.png";

// Redux
import { connect } from "react-redux";
import { loadCurrentItem, addToCart, fetchProducts } from "./action";

const Product = ({
  mapProducts,
  fetchProducts,
  product,
  addToCart,
  loadCurrentItem,
}) => {
  useEffect(() => {
    fetchProducts();  -----> Using it Here !
  }, []);

  return (
    <div className="card-deck d-flex justify-content-center">
      {mapProducts.map((product) => (
        <div className="card item-card" key={product.id} product={product}>
          {/* Admin Card */}
          {/* Header Image */}
          <img className="card-img-top" src={ItemOne} alt="Card image cap" />
          {/* Card Body */}
          <div className="card-body">
            <h4 className="card-title">{product.title}</h4>
            <h5 className="card-title">$ {product.price}</h5>
            <p className="card-text">{product.description}</p>
            <button
              className="btn btn-primary"
              onClick={() => addToCart(product.id)}
            >
              + Add To Cart
            </button>
            <a href="#" className="btn btn-danger">
              <svg
                width="1em"
                height="1em"
                viewBox="0 0 16 16"
                className="bi bi-heart-fill"
                fill="currentColor"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  fillRule="evenodd"
                  d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"
                />
              </svg>
            </a>
          </div>
          {/* Card Footer */}
          <div className="card-footer">
            <small className="text-muted">Last updated 3 mins ago</small>
          </div>
        </div>
      ))}
    </div>
  );
};

const mapStateToProps = (state) => {
  return {
    mapProducts: state.shop.products,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    addToCart: (id) => dispatch(addToCart(id)),
    loadCurrentItem: (item) => dispatch(loadCurrentItem(item)),
    fetchProducts: () => dispatch(fetchProducts()),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Product);

person Ashkan Ebtekari    schedule 18.03.2021    source источник


Ответы (1)


В твоем случае:


  useEffect(() => {
    fetchProducts(page);  -----> Using it Here !
  }, [page]);

//and


    fetchProducts: (page) => dispatch(fetchProducts(page)),

Обратите внимание, что ваш mapDispatchToProps может (и должен) также быть записан в нотации объекта карты:

const mapDispatchToProps = {
  addToCart,
  loadCurrentItem,
  fetchProducts
}

Также обратите внимание, что официальная рекомендация состоит в том, чтобы использовать перехватчики реакции-redux вместо connect и mapDispatchToProps.

Так что пропустите весь материал connect и в вашем компоненте:

const Product = ({
  product,
}) => {
  const mapProducts = useSelector(state => state.shop.products)
  const dispatch = useDispatch()
  useEffect(() => {
    dispatch(fetchProducts(page));
  }, []);

Кроме того, если вы все еще используете connect, возможно, вы следовали устаревшим руководствам. Redux сильно изменился за последние несколько лет. Изучите современный редукс и актуальные официальные руководства по Redux

Кстати: готовится новый API для официального инструментария Redux, который может позаботиться обо всех этих данных за вас. Вы уже можете попробовать его в качестве дополнительного пакета: https://rtk-query-docs.netlify.app/

person phry    schedule 18.03.2021