当前位置: 首页 > 知识库问答 >
问题:

React上下文:组件未呈现

公良育
2023-03-14

在我的React17.0.1 SPA翻译应用程序中,我有一个包含两个部分的页面。顶部用于输入,底部用于该输入的翻译。我在为该页面使用单个上下文/状态时遇到过问题,因为翻译是由远程API执行的,当它返回时,如果不更新输入部分并将其重置为调用翻译API时所保持的值,我就无法更新UI。

因此,我将页面分成两个上下文,一个用于输入,一个用于翻译。到目前为止还好。翻译的渲染是我第一次做的。但是,尽管翻译上下文中的状态在需要时会通过它的简化程序改变(我的日志记录证明了这一点),页面的适当部分不会随着这些改变而重新呈现。正如我所说的,这很奇怪,因为我第一次以这种方式改变状态时,它实际上是重新呈现的。

这张草图更详细地展示了基本结构,但我漏掉了很多:

app.js

import { React, useRef, createContext, useReducer } from "react";
import ReactDOM from 'react-dom';
import { Form } from "react-bootstrap";
import { Translation } from "./Translation";

const NativeContext = createContext();
const TranslationsContext = createContext();

const nativeReducer = (state, action) {...}
const translationsReducer = (state, action) {...}

const App = () {
  const inputControl = useRef(null);
  const [nativeState, nativeDispatch] = useReducer(nativeReducer, {});
  const [translationsState, translationsDispatch] = useReducer(translationsReducer, {});
  const handleChange = async () => {
    // fetch from external API
    translationsDispatch({ type: "TX", payload: { text: text, translations: data.translations } });
  }

  return (
    <NativeContext.Provider value={{ nativeState, nativeDispatch }}>
      <Form.Control key="fc-in" autoFocus ref={inputControl} as="textarea" id="inputControl" defaultValue={nativeState.text} onChange={textChanged} />
    </NativeContext.Provider>
    <TranslationsContext.Provider value={{ translationsState, translationsDispatch }}>
      {translationsState.translations.map((item, index) => {
        return <Translation index={index} item={item} to={item.language} key={`tx-${item.language}`} />;
      })}
    </TranslationsContext.Provider>
  );
}

我用通常的index.js来启动它:

index.js

  ReactDOM.render(<React.StrictMode><App /></React.StrictMode>,document.getElementById('root'));
const nativeReducer = (state, action) => {
  switch (action.type) {
    case "TEXT":
      return {
        ...state,
        text: action.payload.text
      };
  }
};
const initialTranslationsState = {
  to: ["de"],
  translations: [
    {
      language: "de",
      text: "Ich hab keine lust Deutsche zu sprechen"
    }
  ]
};
import { React, useContext } from "react";

export const Translation = props => {
  const { translationsState, translationsDispatch } = useContext(TranslationsContext);
  
  return (
    <Form.Control as="textarea" defaultValue={translationsState.translations[props.index].text} readOnly />
  );
}

传入的道具包含与该组件的特定实例应该引用哪个翻译有关的数据。我不想在道具中传递翻译本身,所以在道具中只传递索引。翻译本身在上下文中传递。

当我进入页面时,NativeContext(指本地语言btw)中已经有一些文本,我有一个useEffect子句调用translate来启动整个过程。这导致翻译被更新,一两秒钟后,我看到屏幕组件呈现结果,而不更新输入文本(事实证明这非常重要)。

但是,当我去编辑输入文本时,翻译结果不会呈现。正如我提到的,我有日志记录来检查状态,它已经适当地改变了,但是在页面上呈现它们的子组件没有被呈现,所以我只能在控制台中看到输出。无论我多久更新一次输入文本,都会发生这种情况。

我有点被这个卡住了。我在stackoverflow上讨论过类似的问题,但它们主要与试图改变状态的人有关,我没有这样做,或者与基于类的旧方法有关,无论如何,这种方法在设计上有缺陷。让我知道如果你需要更多的信息来帮助解决这个问题。

共有1个答案

戚甫
2023-03-14

“...这导致翻译被更新,一两秒钟后,我看到屏幕组件呈现结果,而不更新输入文本”

一旦您获取了翻译,您就将该值单独发送到translationContext。这意味着,所有使用它的组件都将重新呈现。

您的输入组件假定您引用了包装在NativeProvider中的组件,但它不使用translationProvider,因此不会监听任何相关的更改。

 类似资料:
  • 问题内容: 我一直在尝试进行AJAX调用,然后在检索到它之后将其添加到我的视图中。 当前代码实际上什么也没有发生。 问题答案: 您的组件名称必须以大写字母开头,因为以小写字母开头的组件会被搜索为默认DOM元素,例如。对于您的组件,情况并非如此。将其设置为大写即可。 根据文档: 当元素类型以字母开头时,它指的是诸如或的内置组件,并导致将字符串 或“ span”传递给。以大写字母开头的类型,例如,编译

  • 对于在其生命周期的某个点隐藏的组件,呈现它的最佳方式是什么?1)渲染组件,但不显示它(显示:无)。2)只在需要时渲染组件。什么对性能更好?如果组件的道具和状态稍后更新,是否最好让组件存在,但隐藏在虚拟DOM中? 或者这个:

  • 我使用Rails与反应宝石和react-router.js内部资产。我使用webpack为了使用需要 我有我的路线内的应用程序。js: 另外es6。jsx: 当我访问controller_name/index时,默认情况下,它会呈现带有“#hello”链接的“欢迎组件”文本,但单击时,它不会执行任何操作。它仍然在说“欢迎组件” 我做错了什么?

  • 我有一个React应用程序,目前正在使用react-router@4.2.0,当URL更改时,我正在努力渲染特定的组件。 当我尝试访问时,CityList组件返回一个PropTypes错误。我已经尝试在LocationsWrapper中的Route组件中添加,然后再添加Main config,但是,这会影响其他路由,例如,使其变为空。 //浏览器路由器 //路由器配置-(路由) 我最好避免

  • 当我们点击“添加”链接时,我试图呈现需要组件。下面是主要组件的代码: 下面是以防万一的需求组件: 我在第一次单击add链接时实现了我试图实现的目标,即在第一次单击add链接时,need组件没有任何条件地被呈现,当我单击“add”时,need组件再次被呈现,但当我第二次单击“add”链接时,我没有看到任何变化。为什么会这样,我希望在每次单击“Add”链接时呈现Need组件。

  • 我是新来的反应。作为一个学习练习,我正在构建一个国际象棋应用程序 我想根据父级中的状态更改子级的DOM。当前,在父级组件的状态变化时,子级组件没有变化。 PS:请忽略任何语法错误。这段代码是实际代码的精简。如果你想看完整的代码,请看这里