React:在两个组件层次结构之间传递状态的上下文
Posted
技术标签:
【中文标题】React:在两个组件层次结构之间传递状态的上下文【英文标题】:React: Context to pass state between two hierarchies of components 【发布时间】:2019-11-05 12:48:03 【问题描述】:我正在开发一个网站,我希望能够在应用程序的任何位置访问状态信息。我尝试了几种实现状态的方法,但总是收到以下错误消息:
元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。
查看SOS
的渲染方法。
这是我的 SOS->index.js 文件:
import React, useContext from 'react';
import axios from 'axios';
import CONST from '../utils/Constants';
import Grid, Box, Container from '@material-ui/core';
import styled from '@material-ui/styles';
import Header from '../Layout';
import ListItem from './ListItem';
import SOSButton from './SOSButton';
import FormPersonType from './FormPersonType';
import FormEmergencyType from './FormEmergencyType';
import StateContext from '../App';
import Context from '../Context';
export default function SOS()
const componentType, setComponentType = useContext(Context);
const timerOn = false;
//'type_of_person',
const ambulance = false;
const fire_service = false;
const police = false;
const car_service = false;
//static contextType = StateContext;
const showSettings = event =>
event.preventDefault();
;
const handleComponentType = e =>
console.log(e);
//this.setState( componentType: 'type_of_emergency' );
setComponentType('type_of_emergency');
;
const handleEmergencyType = new_emergency_state =>
console.log(new_emergency_state);
// this.setState(new_emergency_state);
;
const onSubmit = e =>
console.log('in OnSubmit');
axios
.post(CONST.URL + 'emergency/create',
id: 1,
data: this.state //TODO
)
.then(res =>
console.log(res);
console.log(res.data);
)
.catch(err =>
console.log(err);
);
;
let component;
if (componentType == 'type_of_person')
component = (
<FormPersonType handleComponentType=this.handleComponentType />
);
else if (componentType == 'type_of_emergency')
component = (
<FormEmergencyType
handleComponentType=this.handleComponentType
handleEmergencyType=this.handleEmergencyType
emergencyTypes=this.state
timerStart=this.timerStart
onSubmit=this.onSubmit
/>
);
return (
<React.Fragment>
<Header title="Send out SOS" />
<StateContext.Provider value="type_of_person" />
<Container component="main" maxWidth="sm">
component
</Container>
/*component = (
<HorizontalNonLinearStepWithError
handleComponentType=this.handleComponentType
/>*/
</React.Fragment>
);
非常感谢您的帮助!
仅供参考,Context文件定义如下:
import React, useState from 'react';
export const Context = React.createContext();
const ContextProvider = props =>
const [componentType, setComponentType] = useState('');
setComponentType = 'type_of_person';
//const [storedNumber, setStoredNumber] = useState('');
//const [functionType, setFunctionType] = useState('');
return (
<Context.Provider
value=
componentType,
setComponentType
>
props.children
</Context.Provider>
);
;
export default ContextProvider;
编辑:我已根据您的建议更改了我的代码(上面已更新)。但现在我收到以下错误: TypeError:无法读取未定义的属性“componentType”
【问题讨论】:
你不能通过这种方式改变affected
的值。需要使用useState
第二个位置返回的函数:const [affected, setAffected] = useState(''); setAffected('type_of_person');
“如果我取消对渲染函数的注释”是什么意思?您正在编写一个功能组件,而不是基于类的组件;它没有render
方法。
您需要阅读函数式组件和类组件! reactjs.org/docs/…
另外,useContext(Context)
会返回一个对象,所以你不能这样做if
:componentType == 'type_of_person'
。您可以使用const affected: componentType = useContext(Context)
访问它
@Macabeus 谢谢你,你能帮我解决在问题编辑中看到的新错误吗?
【参考方案1】:
Context
不是 ../Context
文件的默认导出,因此您必须将其导入为:
import Context from '../Context';
否则,它会尝试导入您的 Context.Provider
组件。
对于您的文件结构/命名,正确的用法是:
// Main app file (for example)
// Wraps your application in the context provider so you can access it anywhere in MyApp
import ContextProvider from '../Context'
export default () =>
return (
<ContextProvider>
<MyApp />
</ContextProvider>
)
// File where you want to use the context
import React, useContext from 'react'
import Context from '../Context'
export default () =>
const myCtx = useContext(Context)
return (
<div>
Got this value - myCtx.someValue - from context
</div>
)
看在上帝的份上...将您的 Context 文件、提供程序和其中的所有内容重命名为更明确的名称。写到这里我都懵了。
【讨论】:
谢谢!除了主应用程序文件之外,如何修改其他文件中的上下文属性? 调用通过上下文传递的 setComponentType 函数。您的上下文(您设置它的方式)是一个对象。因此,当您拨打const myCtx=useContext(Context)
时,您将可以访问myCtx.componentType
和myCtx.setComponentType()
。如果它现在坏了,那是因为你的上下文文件中有setComponentType = 'type_of_person';
。删除它并使用 const [componentType, setComponentType] = useState('type_of_person')
设置您的初始上下文以上是关于React:在两个组件层次结构之间传递状态的上下文的主要内容,如果未能解决你的问题,请参考以下文章