首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >useReducer钩子和减法器函数问题

useReducer钩子和减法器函数问题
EN

Stack Overflow用户
提问于 2021-08-25 23:36:37
回答 1查看 48关注 0票数 1

我认为这主要是我的reducer函数的问题,但基本上我是在尝试添加和删除组件。添加可以正常工作。删除不能正常工作。当我创建一个新组件时,我在onClick中放置了一个控制台日志,它显示了唯一的in,但是它似乎没有被正确地传递到reducer或其他什么地方。如果有人有什么想法,我洗耳恭听。

Reducer函数

代码语言:javascript
复制
export default function reducer(state: any, action: any) {
  switch (action.type) {
    case "ADD_COMPONENT":
      return {
        ...state,
        components: [...state.components, action.payload],
      };
    case "DELETE_COMPONENT":
      return {
        ...state,
        components: state.components.filter(
          (component: any) => component.id == action.payload
        ),
      };
    default:
      return state;
  }
}

这里是Delete键,它过滤并检查一个id,通过这种方式(component.id == action.payload),它删除所有的组件。如果我有!=== action.payload,它不会删除任何东西。

上下文

代码语言:javascript
复制
import React, { createContext, useReducer, useState } from "react";
import ComponentReducer from "./ComponentReducer";

const NewComponentState: NewComponentsState = {
  components: [],
  addComponent: () => {},
  deleteComponent: () => {},
};

export const NewComponentContext =
  React.createContext<NewComponentsState>(NewComponentState);

export const NewComponentProvider: React.FC = ({ children }) => {
 
  const [state, dispatch] = useReducer(ComponentReducer, NewComponentState);

  const addComponent = (component: any) => {
    dispatch({
      type: "ADD_COMPONENT",
      payload: component
    });
  };
  const deleteComponent = (id: any) => {
    dispatch({
      type: "DELETE_COMPONENT",
      payload: id,
    });
  };
  return (
    <NewComponentContext.Provider
      value={{ components: state.components, deleteComponent, addComponent }}
    >
      {children}
    </NewComponentContext.Provider>
  );
};

Notes组件。这是我一直在测试的组件

代码语言:javascript
复制
import { Menu,Transition } from "@headlessui/react";
import React, { useState, Fragment, useContext } from "react";
import NoteColorChanger from "./NoteColor";
import Draggable from 'react-draggable';
import { NewComponentContext } from "../../../Context/NewComponentContext";

interface INote {
  id: any
}
const Note: React.FC <INote> = ({ id }) => {
  const [content, setContent] = useState<string>()
  const [title, setTitle] = useState<string>()
  const [color, setColor] = useState<any>()
  const [position, setPosition] = useState<any>({x: 0, y: 0})

  const {deleteComponent} = useContext(NewComponentContext)

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setContent(event.target.value)
  };

  const handleColor = (notecolor: any) => {
    setColor(notecolor)
  }

  const trackPosition = (pos:any) => {
    setPosition({x: pos.x, y: pos.y})
  }

  return ( 
    <div className={`${color} h-64 w-64 bg-yellow-200 text-black rounded-lg p-2 shadow-lg`}>
      <div className="flex justify-between items-center pb-6">
        <h1 className="font-bold font-Inter">Note</h1>
        <Menu>
          <Menu.Button>
            <div className={`hover:${color} p-1 rounded-lg ease-in-out duration-100`}>
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="h-6 w-6"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={1}
                  d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </div>
          </Menu.Button>
          <Transition
            as={Fragment}
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="transform opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="transform opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <Menu.Items
              as="div"
              className={`bg-gray-100 font-Inter w-64 shadow-lg rounded-lg absolute translate-y-24 -translate-x-2 z-50`}
            >
              <Menu.Item>
                {({ active }) => (
                  <div
                    id="color"
                    className={` flex items-center py-2 px-3 rounded-lg w-full`}
                  >
                    {<NoteColorChanger handleColor={handleColor}/>}
                    
                    
                  </div>
                )}
              </Menu.Item>
              <Menu.Item>
                {({ active }) => (
                  <button
                    id="Todo"
                    className={`${
                      active ? "bg-blue-500 text-white" : "text-black"
                    } flex items-center py-2 px-3 rounded-lg w-full`}
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      className="h-6 w-6 mr-3"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
                      />
                    </svg>
                    Edit Title
                  </button>
                )}
              </Menu.Item>
              <Menu.Item>
                {({ active }) => (
                  <li
                    onClick={() => deleteComponent(id)}
                    className={`${
                      active ? "bg-blue-500 text-white" : " text-black"
                    } flex items-center py-2 px-3 cursor-pointer rounded-lg`}
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      className="h-6 w-6 mr-3"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                      />
                    </svg>
                    Delete Note
                  </li>
                )}
              </Menu.Item>
              
            </Menu.Items>
          </Transition>
        </Menu>
      </div>

      <textarea
        className={`${color} bg-yellow-200 font-Inter w-full h-48 border-none focus:border-none focus:ring-0 resize-none`}
        onChange={() => {handleChange}}
      />
    </div>
   
  );
};
export default Note;

菜单组件

代码语言:javascript
复制
import React, { useContext, Fragment, useState } from "react"
import { NewComponentContext } from "../../Context/NewComponentContext"
import { Menu, Transition } from '@headlessui/react'
import Note from "./Note/Note";
import TodoList from "./Todo/TodoList";
import Photo from "./Photo/Photo";

const NewComponentMenu = () => {
    const { addComponent } = useContext(NewComponentContext)
    const [id, setId] = useState<number>(0)

    const newComponent = (component: any) => {
        setId(Math.floor(Math.random() * 100000000))
        addComponent(component)
    }
    return (
      <div className="w-6 h-6 mt-4 ml-4 shadow-md text-gray-800 font-Inter z-50">
        <Menu>
          <Menu.Button>
            <div className="p-1 rounded-lg bg-blue-500 hover:bg-blue-600 ease-in-out duration-100">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="h-6 w-6 text-blue-50"
                viewBox="0 0 20 20"
                fill="currentColor"
              >
                <path
                  fillRule="evenodd"
                  d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
                  clipRule="evenodd"
                />
              </svg>
            </div>
          </Menu.Button>
          <Transition
            as={Fragment}
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="transform opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="transform opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <Menu.Items as="div" className="w-60 shadow-lg rounded-lg bg-white">
              <h1 className="text-center font-Inter text-2xl pb-2">Items</h1>
 
              <Menu.Item>
                {({ active }) => (
                  <li
                    onClick={() => newComponent(<Note id={id}/>) }
                    className={`${
                      active ? "bg-blue-500 text-white" : " text-black"
                    } flex items-center py-2 px-3 cursor-pointer rounded-lg`}
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      className="h-6 w-6 mr-3"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
                      />
                    </svg>
                    Note
                  </li>
                )}
              </Menu.Item>
            </Menu.Items>
          </Transition>
        </Menu>
      </div>
    );
  };
  
  export default NewComponentMenu;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-26 00:08:09

问题

您遇到的问题是您没有向addComponent回调传递具有id属性的对象。您正在传递JSX文本。将JSX存储到任何React状态通常都是一种反模式,您应该在呈现时存储数据并将其映射到JSX。

解决方案

传递一个具有id属性的对象。在更新状态时,您只需要一个函数来生成id,因此NewComponentMenu中的id状态是不必要的。

代码语言:javascript
复制
const NewComponentMenu = () => {
  const { addComponent } = useContext(NewComponentContext);

  const newComponent = () => {
    addComponent({
      id: Math.floor(Math.random() * 100000000),
    });
  };

  return (
    ...
    <Menu.Item>
      {({ active }) => (
        <li
          onClick={newComponent}
          className={`${
            active ? "bg-blue-500 text-white" : " text-black"
          } flex items-center py-2 px-3 cursor-pointer rounded-lg`}
        >
          ...
        </li>
      )}
    </Menu.Item>
    ...
  );
};

现在您正在使用id属性存储数据元素对象,删除案例应该可以工作了。

在呈现state.components时,您需要映射到Note组件。

代码语言:javascript
复制
const { components } = useContext(NewComponentContext);

...

{components.map(el => <Note id={el.id}/>)}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68930934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档