【问题标题】:React Context API passing values to child components does not workReact Context API 将值传递给子组件不起作用
【发布时间】:2020-04-26 08:46:39
【问题描述】:

我是 ReactJS 和 Context APIs/Hooks 的新手。我有一个基本应用程序,其中父功能组件将值传递给 3 个按钮。但问题是我在按钮上看到了默认值(“欢迎”),而不是我在上下文中设置的值。

Context.js:

import React, {  useState, useContext, useReducer  } from 'react';

const initalDBStates = {Couchbase:[],MongoDB:[],Cassandra:[], jobId: null, results:[],activeDBName: "Welcome"}

export  const AppContext = React.createContext(initalDBStates);

TestGrid.js:

import React, {  useState, useContext, useReducer  } from 'react';
import DBButton from './DBButton';

import {AppContext} from "./Context";

const TestGrid = () =>  {

  const context = useContext(AppContext)

  const setActiveDBName = (activeDBName) => {
    setDBState({...dbState, activeDBName: activeDBName})
  }

  const [dbState,setDBState] = useState({...context, updateJobId:updateJobId,updateResults:updateResults,setActiveDBName:setActiveDBName })



        return(
            <AppContext.Provider value={dbState}>
            <div class="dls-gray-02-bg pad " style={{height: '100%', minHeight: '100vh',}}>
            <div class="row stack-a">
                <div class="display-inline-block">
                    <DBButton onClick={()=>setActiveDBName("Couchbase")}/>

                    <DBButton onClick={()=>setActiveDBName("Cassandra")}/>

                    <DBButton onClick={()=>setActiveDBName("MongoDB")}/>
                </div>
            </div>

            </div>
            </AppContext.Provider>

    )


}
export default TestGrid;

最后是 DBBUtton.js:

import React, { useContext } from 'react';
import {AppContext} from "./Context";

const colors = {"Couchbase":"deep-blue", "MongoDB":"green","Cassandra":"bright-blue"};
function DBButton()   {


        return(
            <AppContext.Consumer>
                {
                    (value) => {
                        let buttonClassName =  "btn btn-contextual dls-" + colors[value.activeDBName];
                        let padClassName = "pad-3 dls-"+ colors[value.activeDBName] + "-bg";
                      return(  
                    <div className="margin-b">
                        <div className={padClassName}>
                            <button className={buttonClassName}>{value.activeDBName}</button>
                        </div>
                    </div>)

                }
                }
            </AppContext.Consumer>
        )


}
export default DBButton;

这 3 个按钮应该显示 Couchbase、Cassandra 和 MongoDB,但它们显示的是默认的白色和我用来初始化上下文的“欢迎”默认值。有人可以帮我吗?无法弄清楚我做错了什么!

【问题讨论】:

    标签: reactjs react-hooks react-context


    【解决方案1】:

    您的项目目前的工作方式如下:

    您正在使用“Welcome”作为 activeDBName 初始化上下文,并且按钮设置为显示 activeDBName 的当前值,这就是它们都显示“Welcome”的原因。您正在传递一个方法,该方法将 activeDBName 的值作为名为“onClick”的道具更改为每个按钮,但按钮组件不使用 onClick 道具(或任何道具),因此当您单击按钮时不会发生任何事情.

    如果您更改代码以使按钮组件将 props.onClick 作为其 onClick 属性传递给实际的 &lt;button&gt; 元素,则单击该按钮将调用 setActiveDBName 方法并将 activeDBName 设置为给定值。单击最上面的按钮会将 activeDBName 更改为“Couchbase”,并且由于按钮组件显示 activeDBName 的当前值,这将导致所有三个按钮都显示“Couchbase”。如果点击第二个按钮,三个按钮都会显示“Cassandra”。

    要让每个按钮显示自己的文本,您需要向按钮传递一个道具来告诉它应该显示什么,并在按钮文本中使用该道具。 (您也可以使用此道具动态生成按钮的 onClick 函数。) 您还应该在您的反应元素上使用className 而不是class

    我假设您没有包含一些额外的 CSS,因为目前唯一应用的样式是在 TestGrid 中的 div 上的 style={{height: '100%', minHeight: '100vh',}}

    我整理了一个沙箱,展示了我上面提到的更改和一个工作示例:https://codesandbox.io/s/sweet-kilby-zomb6?file=/src/DBButton.js

    【讨论】:

    • 感谢香农的回答,但是为什么我在使用上下文 API 时要传递道具?我认为使用 Context 的全部意义在于停止使用道具。
    • Context 的意义在于,如果你想在多个组件之间共享值(特别是在多个嵌套级别),你可以这样做,而无需通过多个组件层传递相同的 prop 或使用像 Redux 这样的 state 容器——不要完全删除 props 的使用。如果你想让自定义按钮组件可重用但显示它自己的文本,你仍然需要告诉每个实例它的文本应该是什么。如果您希望所有按钮显示相同的文本,您可以使用 Context。
    猜你喜欢
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2019-05-28
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2022-11-09
    相关资源
    最近更新 更多