День 94 #100DaysOfCode: Все еще работаю над функцией отмены. Я думаю, что с логикой у меня почти все в порядке. Проблема в том, что ничего не происходит, когда я нажимаю кнопку отмены (😬). Но не волнуйтесь, я использую useRef и useMemo для создания ссылки на каждую карту по определенному индексу, чтобы последнюю карту можно было извлечь и удалить из массива «понравившиеся пользователи» обратно в массив «новые пользователи». В этом сообщении в блоге я объясню, как я реализую функцию отмены, и мой мыслительный процесс, стоящий за ней.

При создании функции смахивания карты кнопка отмены является важной функцией, которая позволяет пользователям отменить действие смахивания. Однако реализовать его не так просто, как может показаться. Основная концепция кнопки отмены состоит в том, чтобы переместить карточку из массива «понравившихся пользователей» обратно в массив «новых пользователей».

Чтобы реализовать функцию отмены, я сначала создал массив для хранения ссылок на каждую карту. Я добился этого с помощью хука useMemo, который гарантирует, что ссылочный массив создается только один раз при первом монтировании компонента.

Затем я создал переменную состояния с именем currentIndex, которая отслеживает текущий индекс карты, которая считывается. Затем я создал хук useRef под названием currentIndexRef, который используется для хранения текущего индекса.

Для обработки логики кнопки отмены я создал функцию handleUndo, которая вызывается при нажатии кнопки отмены. Функция handleUndo сначала проверяет, активна ли кнопка отмены, сравнивая currentIndex с длиной массива notLikedClients. Если кнопка отмены не активна, функция возвращается. В противном случае он увеличивает currentIndex на единицу и обновляет currentIndexRef.

Наконец, функция restoreCard вызывается для последней карточки в массиве notLikedClients. Эта функция возвращает карту в исходное положение, анимируя ее обратно в стопку карт.

Кстати, я провел небольшое исследование реализации функции отмены и наткнулся на этот полезный ресурс:



import React from "react";
import TinderCard from "react-tinder-card";
import "./App.css";
import Mainbuttons from "./mainbuttons";
import { useEffect, useState, useRef, useMemo } from "react";
import axios from "./axios.js";
import Chat from "./Chat";
import { useCookies } from "react-cookie";

function Customer({ isClient, isFreelancer, user, getUser, undo }) {
  const [clients, setClients] = useState([]);
  const [cookies, setCookie, removeCookie] = useCookies(["user"]);
  const [lastDirection, setLastDirection] = useState(null);

  const userId = user && user["user_id"];

  useEffect(() => {
    async function fetchData() {
      const req = await axios.get("/clientuser");

      setClients(req.data);
    }

    fetchData();
  }, []);

  const likeClient = async (likedClientId) => {
    try {
      await axios.put("/addLikedClients", {
        userId,
        likedClientId,
      });
      getUser();
    } catch (error) {
      console.log(error);
    }
  };

  const swiped = (direction, likedClientId, index) => {
    if (direction === "up") {
      likeClient(likedClientId);
    }
    setLastDirection(direction);
    updateCurrentIndex(index - 1);
  };

  const outOfFrame = (name) => {
    console.log(name);
  };

  const likedClientIds =
    user?.connects?.map(({ user_id }) => user_id).concat(userId) ?? [];

  const notLikedClients = clients?.filter(
    (person) => !likedClientIds.includes(person.client_user_id)
  );

  const [currentIndex, setCurrentIndex] = useState(notLikedClients.length - 1);
  const currentIndexRef = useRef(currentIndex);

  const activeUndo = currentIndex < notLikedClients.length - 1;

  const activeSwipe = currentIndex >= 0;

  const childRefs = useMemo(
    () =>
      Array(notLikedClients.length)
        .fill(0)
        .map((i) => React.createRef()),
    []
  );

  const updateCurrentIndex = (value) => {
    setCurrentIndex(value);
    currentIndexRef.current = value;
  };

  const handleUndo = async () => {
    try {
      if (!activeUndo) return;
      const newIndex = currentIndex + 1;
      updateCurrentIndex(newIndex);
      await childRefs[newIndex].current.restoreCard();
    } catch (err) {
      console.log(err);
    }
  };

  // the undo button is clicked
  useEffect(() => {
    if (undo) {
      handleUndo();
    }
  }, [undo]);

  return (
    <>
      {user && (
        <div className="contractrOne">
          <div className="cardContainer">
            {notLikedClients.map((person, index) => (
              <TinderCard
                ref={childRefs[index]}
                className="swipe"
                key={index}
                preventSwipe={["left", "right"]}
                onSwipe={(dir) => swiped(dir, person.client_user_id, index)}
                onCardLeftScreen={() =>
                  outOfFrame(person.client_first_name, index)
                }
              >
                <div
                  style={{ backgroundImage: "url(" + person.client_url + ")" }}
                  className="card"
                >
                  <h2>{person.client_first_name}</h2>
                  <h4>Looking for: {person.client_talent}</h4>
                  <p>Max Hourly Rate: {"$" + person.client_rate + "/hr"}</p>
                  <img
                    style={{ filter: "inverse" }}
                    className="ratingImg"
                    src={person.ratingUrl}
                  />
                </div>
              </TinderCard>
            ))}
          </div>
        </div>
      )}
    </>
  );
}

export default Customer;