简体   繁体   English

为什么我的 React Context Helper 函数使用过时的 state?

[英]Why do my React Context Helper functions use outdated state?

Thank you for taking a look at this...谢谢你看这个...

Here's my problem;这是我的问题; in my react native app I have written a React Context that manages "Header Messages" that I can call anywhere in the code base and attach a message under the Header element of my app (Displayed Globally).在我的 react native 应用程序中,我编写了一个 React Context 来管理“标题消息”,我可以在代码库中的任何位置调用它,并在我的应用程序的 Header 元素下附加一条消息(全局显示)。 This process works and I am able to render my first Header Message that I add using the helper function.addNewMessage('id', 'JSX.Element');这个过程有效,我能够呈现我使用帮助程序 function.addNewMessage('id', 'JSX.Element') 添加的第一个 Header 消息; but when I call this again;但是当我再次调用它时; the previous message is removed and the new message is displayed...上一条消息被删除并显示新消息...

I believe this is happening because because the function.addNewMessage() defined in the context shared below references state... Calling it updates state... then calling it again;我相信这是因为在下面共享的上下文中定义的 function.addNewMessage() 引用了 state... 调用它会更新 state... 然后再次调用它; its still referencing the original state... See the console logs to see how this plays out with two subsequent calls.它仍然引用原始的 state ... 查看控制台日志以了解这如何在随后的两个调用中发挥作用。

Code Behind the Context;上下文背后的代码; Helper functions are declared in the function...辅助函数在 function 中声明...

import * as React from 'react';
import { Text } from 'react-native';

export interface IElements {
  [key: string] : JSX.Element;
}

export interface IState {
  setState : (newState: IState) => void;
  addNewMessage : (id: string, elem: JSX.Element) => void;
  removeMessage : (id: string) => void;
  returnAllMessages : () => JSX.Element[]
  messages : IElements;
}

export interface IProps {
  children : JSX.Element[] | JSX.Element;
}

const defaultValues: IState = {
  setState: () => undefined,
  addNewMessage: () => undefined,
  removeMessage: () => undefined,
  returnAllMessages: () => [],
  messages : {'test1': <Text>FooBarLoremIpsum</Text>},
};

export const HeaderMessagesContext: React.Context<IState> = React.createContext<IState>(defaultValues);

const CTX_HeaderMessages: React.FC<IProps> = (props: IProps) => {
  const [state, updateState] = React.useState(defaultValues);

  // Every time I call this function, it is acting like it is using
  // defaultValues instead of state... I assume this is a weird side effect
  // of defining a function then storing an instance of that function inside
  // the state object itself...? But anytime I try and declare a side effect
  // that would essentially store a new instance of the function; I find myself
  // in an infinite Loop... I'm struggling with the pattern here to make this work :/
  const addNewMessage = (id: string, elem : JSX.Element) => {
    console.log('State Coming into "AddNewMessage"', state);
    const newMessages = {...state.messages};
    newMessages[id] = elem;
    console.log('State Exiting "AddNewMessage"', {...state, messages : newMessages});
    updateState({...state, messages : newMessages});
  };
  const removeMessage = (id: string) => { if(state.messages[id]) {delete state.messages[id]} }
  const returnAllMessages = () => Object.keys(state.messages).map(key => state.messages[key]);

  const val: IState = {
    ...state,
    setState : updateState,
    addNewMessage,
    removeMessage,
    returnAllMessages
  }

  return (
    <HeaderMessagesContext.Provider value={val}>
      {props.children}
    </HeaderMessagesContext.Provider>
  );
};

export default CTX_HeaderMessages;

Chrome Console Logs Chrome 控制台日志

These logs show what I am experiencing... I'd like to draw your attention to the value of the messages object.这些日志显示了我正在经历的... 我想提请您注意消息 object 的价值。 When I call the function the first time;当我第一次调用 function 时; the value is added;增值; when I call the function a second time;当我第二次调用 function 时; Notice the value from the first call (on the previous line) is not present...请注意,第一次调用的值(在上一行)不存在...

State Comming into "AddNewMessage" 
    {messages: {…}, setState: ƒ, addNewMessage: ƒ, removeMessage: ƒ, returnAllMessages: ƒ}
    addNewMessage: ƒ addNewMessage()
    messages: {test1: {…}}
    removeMessage: ƒ removeMessage()
    returnAllMessages: ƒ returnAllMessages()
    setState: ƒ setState()
    __proto__: Object

HeaderMessages.tsx:38 State Exiting "AddNewMessage" 
    {messages: {…}, setState: ƒ, addNewMessage: ƒ, removeMessage: ƒ, returnAllMessages: ƒ}
    addNewMessage: ƒ addNewMessage()
    messages: {test1: {…}, SuggestUpdate_Line78: {…}}
    removeMessage: ƒ removeMessage()
    returnAllMessages: ƒ returnAllMessages()
    setState: ƒ setState()
    __proto__: Object

HeaderMessages.tsx:35 State Comming into "AddNewMessage" 
    {messages: {…}, setState: ƒ, addNewMessage: ƒ, removeMessage: ƒ, returnAllMessages: ƒ}
    addNewMessage: ƒ addNewMessage()
    messages: {test1: {…}}
    removeMessage: ƒ removeMessage()
    returnAllMessages: ƒ returnAllMessages()
    setState: ƒ setState()
    __proto__: Object

HeaderMessages.tsx:38 State Exiting "AddNewMessage" 
    {messages: {…}, setState: ƒ, addNewMessage: ƒ, removeMessage: ƒ, returnAllMessages: ƒ}
    addNewMessage: ƒ addNewMessage()
    messages: {test1: {…}, SuggestUpdate_Line79: {…}}
    removeMessage: ƒ removeMessage()
    returnAllMessages: ƒ returnAllMessages()
    setState: ƒ setState()
    __proto__: Object

Passing setState in your context is redundant I think.我认为在您的上下文中传递 setState 是多余的。 and you just need to store the messages in your state, not the CRUD methods.您只需要将消息存储在 state 中,而不是 CRUD 方法中。 take a look at below code, I think it'll work.看看下面的代码,我认为它会工作。

import * as React from 'react';
import { Text } from 'react-native';

export interface IElements {
  [key: string] : JSX.Element;
}

export interface IState {
  addNewMessage : (id: string, elem: JSX.Element) => void;
  removeMessage : (id: string) => void;
  returnAllMessages : () => JSX.Element[]
  messages : IElements;
}

export interface IProps {
  children : JSX.Element[] | JSX.Element;
}

const defaultValues: IState = {
  addNewMessage: () => undefined,
  removeMessage: () => undefined,
  returnAllMessages: () => [],
  messages: { test1: <Text>FooBarLoremIpsum</Text> },
};

const defaultMessages : IElements = {
  messages: { test1: <Text>FooBarLoremIpsum</Text> },
};

export const HeaderMessagesContext: React.Context<IState> = React.createContext<IState>(defaultValues);

const CTX_HeaderMessages: React.FC<IProps> = (props: IProps) => {
  const [state, updateState] = React.useState<IElements>(defaultMessages);

  // Every time I call this function, it is acting like it is using
  // defaultValues instead of state... I assume this is a weird side effect
  // of defining a function then storing an instance of that function inside
  // the state object itself...? But anytime I try and declare a side effect
  // that would essentially store a new instance of the function; I find myself
  // in an infinite Loop... I'm struggling with the pattern here to make this work :/
  const addNewMessage = (id: string, elem : JSX.Element) => {
    console.log('State Coming into "AddNewMessage"', state);
    const newMessages = { ...state };
    newMessages[id] = elem;
    console.log('State Exiting "AddNewMessage"', newMessages);
    updateState(newMessages);
  };
  const removeMessage = (id: string) => { if (state[id]) { delete state[id]; } };
  const returnAllMessages = () => Object.keys(state).map((key) => state[key]);

  const val: IState = {
    messages: state,
    addNewMessage,
    removeMessage,
    returnAllMessages,
  };

  return (
    <HeaderMessagesContext.Provider value={val}>
      {props.children}
    </HeaderMessagesContext.Provider>
  );
};

export default CTX_HeaderMessages;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 React Context 中,如何在 state 函数中使用 state 变量? - In React Context, how can I use state variables in state functions? 我的辅助函数放在哪里? - Where do I put my helper functions? 当我使用 React 钩子和 React 上下文添加新帖子时,为什么我的 state 会替换我的帖子 - Why is my state replacing my posts when I add a new one using React hooks and React context 反应挂钩回调接收过时的状态 - React hooks callback receives outdated state 在 React useEffect 钩子中引用过时的状态 - Referencing outdated state in React useEffect hook 为什么我的React孙子组件在收到其父组件的道具更改后没有更新? 或者:我需要使用状态吗? - Why does my React grandchild component not update after receiving a change in props from its parent? Or: do I need to use state? 我如何使用上下文在React中的类和功能组件之间共享状态? - How do I use context to share state between a class and a functional component in react? React Context 更新 state 在使用 Hooks 时没有反映在嵌套函数中 - React Context updated state not reflecting in nested functions when using Hooks React:为什么我们不需要将上下文绑定到用作事件侦听器的箭头函数? - React: Why do we not need to bind context to arrow functions being used as event listeners? 函数会在 React 中获取最新的状态值吗? - Do functions get the latest state value in React?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM