簡體   English   中英

使用 useReducer 和 React Context API 時 Reducer 運行兩次

[英]Reducer running twice when using useReducer and React Context API

在使用 React Context API 以及 useReducer 和 useContext 掛鈎的奇怪情況下,我有點撞牆了。

這是我的主要商店。

import React, { createContext, useReducer } from 'react';
import { Reducers } from './Reducers';
import { surveys } from '../../testData.json';

export const context = createContext();
const { Provider } = context;

export const Store = ({ children }) => {
  const [store, dispatch] = useReducer(Reducers, {
    editSurvey: { display: false },
    surveys,
  });
  return <Provider value={{ store, dispatch }}>{children}</Provider>;
};

這是我的 Reducers 函數和我的 Action 類型:

import { Actions } from './Actions';
const { DISPLAY_NEW_SURVEY, HIDE_SURVEY } = Actions;
export const Reducers = (state, action) => {
  const { type, payload } = action;
  console.log(state, action);
  switch (type) {
    case DISPLAY_NEW_SURVEY:
      return { ...state, editSurvey: { display: true } };
    case HIDE_SURVEY:
      return { ...state, editSurvey: { display: false } };
    default:
      return state;
  }
};
export const Actions = {
  DISPLAY_NEW_SURVEY: 'DISPLAY_NEW_SURVEY',
  HIDE_SURVEY: 'HIDE_SURVEY',
};

我的編輯屬性中有一個顯示屬性,用於有條件地呈現反應門戶,見下文:

import React, { useContext } from 'react';
import { EditSurveyPortal } from '../EditSurvey/EditSurveyPortal';
import { context } from '../../store/Store';

export const NavItem = ({ name, NavImage }) => {
  const { dispatch } = useContext(context);
  return (
    <div
      id={name}
      style={{ cursor: 'pointer' }}
      onClick={() => {
        dispatch({ type: 'DISPLAY_NEW_SURVEY' });
      }}
    >
      <NavImage alt={name} width={10} height={10} />
      <EditSurveyPortal />
    </div>
  );
};
import React, { useContext } from 'react';
import { createPortal } from 'react-dom';
import { context } from '../../store/Store';
import { EditSurvey } from './EditSurvey';

export const EditSurveyPortal = () => {
  const {
    store: {
      editSurvey: { display },
    },
    dispatch,
  } = useContext(context);
  return display
    ? createPortal(
        <div className="absolute top-0 left-0 w-screen h-screen z-10 flex justify-center items-center bg-gray-400 bg-opacity-50">
          <EditSurvey />
        </div>,
        document.getElementById('root'),
      )
    : null;
};

這是實際的編輯調查組件:

import React from 'react';
import { Card, CardHeader } from '../Utility/Card';
import { Close } from '../Images/Close';

export const EditSurvey = ({ dispatch }) => {
  return (
    <Card>
      <CardHeader className="flex justify-between align-center">
        <div className="inline-block relative rounded">
          <span className="absolute top-0 l-0 bg-gray-200 text-gray-800 rounded-l px-2 py-1">
            Title
          </span>
          <input type="text" className="rounded p-1" />
        </div>
        <div
          className="text-gray-800"
          style={{ cursor: 'pointer' }}
          onClick={() => {
            dispatch({ type: 'HIDE_SURVEY' });
          }}
        >
          <Close width={8} height={8} />
        </div>
      </CardHeader>
    </Card>
  );
};

我的問題是,當我單擊門戶上的關閉按鈕時,它會分派 HIDE_SURVEY,然后立即分派 DISPLAY_NEW_SURVEY:

頁面截圖

我一生都無法弄清楚這一點。 任何幫助將不勝感激。

謝謝!

事件冒泡,伙計。

這里的問題是您的EditSurvey位於 NavItem 的可點擊區域下方。 這里發生的事情是,當您在EditSurvey單擊該 div 時,它首先注冊該 div 上的單擊,然后冒泡到您的 NavItem 可點擊 div。 這基本上就是所謂的event-bubbling

您可以在此處了解事件冒泡和捕獲

此外,您也可以在此處檢查事件冒泡問題

為了阻止事件冒泡,您可以簡單地停止事件的傳播。

<div
    className="text-gray-800"
    style={{ cursor: 'pointer' }}
    onClick={(event) => {
      event.stopPropagation();
      dispatch({ type: 'HIDE_SURVEY' });
    }}
  >
    <Close width={8} height={8} />
  </div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM