Как программно перенаправить реакцию в пределах состояния?

#javascript #reactjs #routes #state

#javascript #reactjs #маршруты #состояние

Вопрос:

Я новичок в React и использую Zustand для работы с глобальными магазинами. Моя цель в данном конкретном случае — перенаправить на страницу «RSVP», если найден правильный пользователь.

Сценарий A: Пользователь найден в базе данных. Переход на новую страницу

Сценарий B: пользователь не найден в базе данных. Оставайтесь на текущей странице и выводите сообщение об ошибке

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

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

 import create from 'zustand';
import { mountStoreDevtool } from 'simple-zustand-devtools';
import { useHistory } from "react-router-dom";


const useStore = create((set, get) => ({
  guests: [],
  currentGuests: [],
  message: "Please enter your unique password found in your email.",
  returnDatabase: (input) => {
    const guests = get().guests;

    const targetParty = guests.filter((guest) => guest.party === input);
    
    if (targetParty.length !== 0) {
      set({ currentGuests: targetParty });
      const setMessage = "Please enter your unique password found in your email.";
      set({ message: setMessage });

      //I want to programatically redirect here
      let history = useHistory();
      history.push("/rsvp");

    } else {
      const setMessage = "Your password has not been found. Please check your email and try again.";
      set({ message: setMessage });
    }
  
  },
  setStore: (data) => {
    const guestsData = data.guests;
    set({ guests: guestsData });
  },
}));
 

Однако я получаю эту ошибку:

 Failed to compile
src/store/storeUtil.js
  Line 19:21:  React Hook "useHistory" is called in function "returnDatabase" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter  react-hooks/rules-of-hooks

Search for the keywords to learn more about each error.
 

Я полагаю, это потому, что его нет в функции, поэтому я попытался поместить его в отдельный компонент:

 import create from 'zustand';
import { mountStoreDevtool } from 'simple-zustand-devtools';
import { useHistory } from "react-router-dom";

  export function RsvpButton(){
    let history = useHistory();
  
    function handleClick() {
      history.push("/rsvp");
    }
  
    return (
      {handleClick}
    );
  }


const useStore = create((set, get) => ({
  guests: [],
  currentGuests: [],
  message: "Please enter your unique password found in your email.",
  returnDatabase: (input) => {
    const guests = get().guests;

    const targetParty = guests.filter((guest) => guest.party === input);
    
    if (targetParty.length !== 0) {
      set({ currentGuests: targetParty });
      const setMessage = "Please enter your unique password found in your email.";
      set({ message: setMessage });

      //try to use component here 
      <RsvpButton />

...etc
 

И это просто ничего не делает / не имеет ошибок. Должен ли я использовать другой метод для маршрутизации на страницу RSVP, отличную от useHistory? Или я делаю что-то не так в своей реализации?

Ответ №1:

Ваш компонент кнопки rsvp but не создает кнопку.

Код для функции RSVP Button должен быть примерно таким

 export function RsvpButton () {
    ... 
    return (
        <button onClick={handleClick}>Rsvp</button>
    ) 
}
 

Таким образом, handleClick функция будет связана со onClick свойством кнопки, что заставит ее запускаться при нажатии кнопки.

Комментарии:

1. Привет, Ритурадж, спасибо за ответ. Моя проблема в том, что я хочу, чтобы он запускался вручную (т. Е. Не По щелчку) в зависимости от логики. Если пользователь находится в списке: инициируйте маршрут, если пользователя нет в списке: оставайтесь на той же странице и выводите сообщение об ошибке, я отредактирую вопрос для большей ясности.

Ответ №2:

Решение для всех, у кого есть подобная проблема:

Чтобы решить эту проблему, я поместил обработчик useHistory в родительский компонент RsvpContainer.js

 import { useHistory } from 'react-router-dom';
    useEffect(() => {
      loadData();
    });
    return (
        <React.Fragment>
            <div className="header">
                <div className="Bg section-2"></div>
                <div className="divider"></div>
                <div className="App section-2">
                    <h3>RSVP.</h3>
                    <h2>Saturday 30 October, 2021</h2>
                    <Input 
                        filter={filter} 
                        setFilter={setFilter}
                        returnDatabaseHandler={returnDatabaseHandler}
                        onUserFound={onUserFoundHandler}
                    />
                        
                </div>
            </div>
        </React.Fragment>
    )
 

Input.js

 export function Input({ setFilter, filter, onUserFound }) {
  const isUserFound = useStore((state) => state.isUserFound);

  useEffect(() => {
    if (isUserFound) {
      onUserFound();
    }
  }, [isUserFound]);

}
 

storeUtil.js (zustand global store) — я добавил это в ‘returnDatabase’

   set({
    message: setMessage,
    isUserFound: true
  });