javascript - 在 React 中使用 useContext 使状态在整个应用程序中可用
问题描述
我尝试使用useContext
并浏览了一些 YT 视频,但我认为我没有得到它......显然我没有。哈
我想在this.state.dropdown
整个应用程序中都可用,所以我可以对其值进行一些条件逻辑。
// input.js
import React from 'react';
import axios from 'axios';
import Button from '../components/button';
import { getData } from '../utils/debugger';
import { DropdownContext } from '../utils/DropdownContext';
// Make a separate function for axios call so that you can reuse it
function queryData(dropdownValue) {
return axios({
method: 'GET',
url: `http://xxx/debugger/${dropdownValue}`,
})
.then((res) => res.data.map((k) => k['key']['name']))
.catch((err) => console.error(err));
}
class InputForm extends React.Component {
// Just use the state property. No need to use constructor
state = {
isLoaded: false,
dropdown: 'RTS',
value: '',
data: [],
};
// If you use arrow function then you don't have to
// bind them in the constructor
handleChange = (event) => {
this.setState({ value: event.target.value });
};
handleDropdown = async (event) => {
// Here we need to query the data from axios
// If we get the data then we'll update the state
// otherwise you may show any error message
const value = event.target.value;
try {
const newData = await queryData(value);
this.setState({ data: newData, dropdown: value });
if (newData.length > 0) {
this.setState({ value: newData[0] });
}
console.log('newData = ' + JSON.stringify(newData));
} catch (ex) {
console.error('Could not get data from axios');
}
};
handleSubmit = (event) => {
event.preventDefault();
};
componentDidMount() {
queryData(this.state.dropdown)
.then((data) => {
this.setState({ data: data });
if (data && data.length > 0) {
this.setState({ value: data[0] });
}
})
.catch(() => {
this.setState({ isLoaded: false });
// Do other stuff here, may be show any error message?
// Could not get data
});
}
render() {
return (
<form onSubmit={this.handleSubmit} className='flex items-center'>
<DropdownContext.Provide value={this.state.dropdown}>
<select
value={this.state.dropdown}
onChange={this.handleDropdown}
className='relative w-full bg-white border border-gray-300 rounded-md shadow-sm px-1 py-3 text-center cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm mr-5'>
<option value='RTS'>RTS</option>
<option value='RTB'>RTB</option>
<option value='MPC'>MPC</option>
<option value='MPC_DSP'>MPC_DSP</option>
</select>
</DropdownContext.Provide>
<select
value={this.state.value}
onChange={this.handleChange}
className='relative w-full bg-white border border-gray-300 rounded-md shadow-sm px-1 py-3 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm mr-5'>
{this.state.data.map((r) => (
<option key={r} value={r}>
{r}
</option>
))}
</select>
{console.log('---')}
{console.log('these will be entered into the getData()')}
{console.log(`this.state.dropdown = ${this.state.dropdown}`)}
{console.log(`this.state.value = ${this.state.value}`)}
<Button onClick={() => getData(this.state.dropdown, this.state.value)} color='green'>
Generate
</Button>
</form>
);
}
}
export default InputForm;
// App.js
import React, { useState, useContext } from 'react';
import './index.css';
import Button from '../src/components/button';
import RTSButtons from '../src/components/rtsButtons';
import RTBButtons from '../src/components/rtbButtons';
import MPCButtons from '../src/components/mpcButtons';
import { DropdownContext } from '../src/utils/DropdownContext';
const sectionStyles = 'mt-5 border-b pb-5';
export default function App() {
const [buttonStatus, setButtonStatus] = useState('rts');
const dropdownState = useContext(DropdownContext);
const switchButtons = (x) => {
setButtonStatus(x);
};
let buttonName = 'RTS / MPC DSP';
let buttons;
if (buttonStatus === 'rts') {
buttonName = 'RTS / MPC DSP';
buttons = <RTSButtons />;
} else if (buttonStatus === 'rtb') {
buttonName = 'RTB';
buttons = <RTBButtons />;
} else if (buttonStatus === 'mpc') {
buttonName = 'MPC';
buttons = <MPCButtons />;
}
return (
<div>
<section id='response' className={`flex justify-between ${sectionStyles}`}>
<div>
<Button onClick={() => switchButtons('rts')} color='gray'>
RTS / MPC DSP
</Button>
<Button onClick={() => switchButtons('rtb')} color='gray'>
RTB
</Button>
<Button onClick={() => switchButtons('mpc')} color='gray'>
MPC
</Button>
</div>
<div>
<Button color='red'>
<a href='http://exchange-debugger' target='_blank' rel='noreferrer'>
create a capture
</a>
</Button>
<Button onClick={() => console.log('Feedback was giving')} color='purple'>
<a
href='https://docs.google.com/forms/d/e/1FAIpQLSfzebOfAeXqGLqAp5E1l2fW1nTqSzYRwpqKG56HPXey9GQLcA/viewform'
target='_blank'
rel='noreferrer'>
feedback
</a>
</Button>
</div>
</section>
<section>
<h2 className='font-bold text-2xl capitalize -mb-10 mt-2'>{buttonName}</h2>
{dropdownState} // <-- just testing the value here
</section>
<section>{buttons}</section>
</div>
);
}
// DropdownContext.js
import { createContext } from 'react';
export const DropdownContext = createContext(null);
这些是我的组件,但我收到以下错误:
错误:元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。检查InputForm
.
我不太确定下一步该去哪里找任何人都可以提供帮助,那就太好了
解决方案
正如 React 文档中所述:“上下文提供了一种通过组件树传递数据的方法,而无需在每个级别手动传递道具”。要传递的状态在您的InputForm
类中定义,因此使用上下文将允许您state.dropdown
访问InputForm
. 似乎您想从App
类中访问状态,但我看不到这样的组件是InputForm
. 如果是这种情况,那么您需要在组件的共同祖先中定义状态,并将其移动DropdownContext.Provider
到该祖先。
推荐阅读
- django - 如何过滤图像?
- azure-ad-b2c - 用于创建 AzureADB2C 的 Azure Fluent Api
- r - 有没有办法在不使下游目标无效的情况下将 file_in 输入的绝对路径更改为 drake?
- javascript - Laravel newly added javascript files give an error net::ERR_ABORTED 404 (Not Found)
- c# - 使用 NLOG 时无法解析服务时缺少详细信息
- c++ - (C++) 异常未处理 - 无效向量
下标 - node.js - 如何使用 express 将我的 mongoDB 查询显示为 json?
- r - 如何使用 barplot() 手动分配沿 x 轴的条形位置?
- c# - 获取计划返回 401 - 未经授权
- php - 如何在 PHP 中分配具有多个返回的变量?