【问题标题】:accessing the 'this' keyword in a react functional component在反应功能组件中访问“this”关键字
【发布时间】:2021-05-25 05:53:15
【问题描述】:

我试图了解如何制作一个可以将自己从具有功能组件的组件数组中移除的组件。这是我正在尝试做的示例代码:

const App = () => {
    <ObjState>
        <ObjectCreator />
        <ObjectList />
    </ObjState>
}

const ObjContext = createContext();

const ObjReducer = (state, { type, payload }) => {
    switch(type) {
        case Types.ADD_OBJ:
            return {
                ...state,
                objects: [...state.objects, payload]
            };
        case Types.REMOVE_OBJ:
            return {
                ...state,
                objects: state.objects.filter(obj => obj !== payload)
            };
        default:
            return state;
    }
}

const ObjState = ({ children }) => {
    const initialState = {
        objects: []
    }

    const [state, dispatch] = useReducer(ObjRecuder, initialState);

    const addObj = (obj) => {
        dispatch({
            type: Types.ADD_OBJ,
            payload: obj
        });
    }

    const removeObj = (obj) => {
        dispatch({
            type: Types.REMOVE_OBJ,
            payload: obj
        });
    }

    return (
        <ObjContext.Provider value={{
            objects: state.objects,
            addObj,
            removeObj
        }}>
            {children}
        </ObjContext.Provider>
    );
}

const ObjCreator = () => {
  const { addObject } = useContext(ObjContext);
  const createObj =() => {
    const obj = (<ObjectTypeA key={uuid()} />);
    addObject(obj);
  }
  return (<button onClick={createObj}>create an object!</button>)
}

const ObjectList = () => {
  const { objects } = useContext(ObjContext)
  return (
    <fragment>
      {objects}
    </fragment>
  )
}

const ObjectTypeA = ({ key }) => {
  const { removeObj } = useContext(ObjContext);
  const removeSelf = () => {
      removeObj(this);
  }
  return (
    <button onClick={removeSelf}>remove me!</button>
  )
}

问题是您不能在最终的Object 组件中引用this。 我有唯一的密钥,但我不确定如何正确传递它。我试图构建一个减速器动作,从Object 中取出key 并以这种方式删除它,但keyundefined 的形式返回,即使它是从道具中解构出来的,我正在使用箭头函数保存它。

我觉得我处理这个问题的方式不对。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    问题

    我认为当你试图在你的上下文状态中存储看起来像 React 组件的东西时,你偏离了方向,你应该存储对象。对象应具有唯一的 GUID。这允许 reducer 识别要从状态中删除的对象元素。然后ObjectList 应该从存储的状态渲染派生的 React 组件。

    我试图构建一个从 对象并以这种方式删除它,但键甚至返回为未定义 虽然它是从道具中解构出来的,我正在使用箭头 保存它的功能。

    这是因为 React 键(和 refs)实际上并不是 props。无法在子组件中访问键。不过,您几乎可以通过任何其他命名道具传递相同的值。请注意以下解决方案中我传递了一个 React 键 一个 id 属性。

    解决方案

    ObjectCreator:创建对象,而不是 React 组件

    const ObjectCreator = () => {
      const { addObj } = useContext(ObjContext);
      const createObj = () => {
        const obj = {
          id: uuid()
        };
        addObj(obj);
      };
      return <button onClick={createObj}>create an object!</button>;
    };
    

    SpecificObject:将其id 传递给removeObj 回调。

    const MyObject = ({ id }) => {
      const { removeObj } = useContext(ObjContext);
      const removeSelf = () => {
        removeObj(id);
      };
      return (
        <div>
          <button onClick={removeSelf}>remove {id}</button>
        </div>
      );
    };
    

    ObjectList:渲染映射到 JSX 的上下文 objects

    const ObjectList = () => {
      const { objects } = useContext(ObjContext);
      return (
        <>
          {objects.map((el) => (
            <MyObject key={el.id} id={el.id} />
          ))}
        </>
      );
    };
    

    在remove object reducer中检查传递的id payload

    const ObjReducer = (state, { type, payload }) => {
      switch (type) {
        case Types.ADD_OBJ:
          return {
            ...state,
            objects: [...state.objects, payload]
          };
        case Types.REMOVE_OBJ:
          return {
            ...state,
            objects: state.objects.filter((obj) => obj.id !== payload)
          };
        default:
          return state;
      }
    };
    

    演示

    【讨论】:

    • 你用 id / key 的东西一针见血,我没有意识到他们会剥夺对道具的访问权。但据我所知,状态中的 JSX 对象数组没有任何问题,它们和其他对象一样。
    • 可以将各种javascript类型放入状态,但我不建议这样做。通常的做法是只在 state 中使用 json 数据。它使理解、测试和调试变得更容易。
    • 问题是我需要数组包含具有特定回调和功能的不同组件。
    • @JakeBlackwell 如果它只是一个普通的 JSX 文字,我想我可能会同意你将它们存储在状态中,但你正在尝试存储一个实例化的 React 组件,它基本上是一个快照来自该渲染周期的那个组件。一旦你尝试做任何“React-y”的事情,比如访问/更新状态,由于 javascript 附件,事情往往会变得有点奇怪。您可以在状态中存储“动态”数据,包括要渲染的组件类型,并且在映射数据时,您只需查找数据应该渲染到哪个组件。
    • @JakeBlackwell 见Choosing the Type at Runtime。正如 Haken 指出的那样,特定组件会处理获取所需的正确回调。
    猜你喜欢
    • 2021-12-12
    • 2017-01-22
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多