我是Reactjs的初学者,并试图通过一个项目来提高自己。随着项目的进行,我现在需要设置一个结构,以便我的UI组件连接到某个RESTAPI,并使用返回的数据。这在互联网上有很多例子,很好。
我的问题是,我是否以及如何将应用编程接口连接与实际的用户界面组件分开。我相信这可能是好的,因为我将有机会在各种用户界面组件中重用应用编程接口连接功能。(在这些帮助器方法中执行与API连接相关的常见任务是理想的。)
为此,我创建了一个PrimaryForm.js文件,即UI组件。对于API调用,我创建了一个APIManager.js文件。理想情况下,APIManager不应该有任何jsx,而只有返回API调用结果到PrimaryF的函数orm.js.
我正在分享我迄今为止编写的代码,以实现这一点。
PrimaryForm.js,删除对APIManager.js的API调用(请参阅下面的HandleTestConnection部分):
import React from 'react';
import withStyles from '@material-ui/styles/withStyles';
import {Link, withRouter } from 'react-router-dom';
import Paper from '@material-ui/core/Paper';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';
import OutlinedInput from '@material-ui/core/OutlinedInput';
import Select from '@material-ui/core/Select';
import FormHelperText from '@material-ui/core/FormHelperText';
import PrimaryFormValidator from '../../validators/PrimaryFormValidator'
import styles from '../../Styles';
import Grid from '@material-ui/core/Grid';
import Tooltip from '@material-ui/core/Tooltip';
import CancelIcon from '@material-ui/icons/Cancel';
import BackIcon from '@material-ui/icons/ArrowBackIosRounded';
import TestIcon from '@material-ui/icons/Power';
import ForwardIcon from '@material-ui/icons/ArrowForwardIosRounded';
import Button from '@material-ui/core/Button';
import APIManager from '../../managers/APIManager';
function PrimaryForm(props) {
const { classes } = props;
const inputLabel = React.useRef(null);
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {setLabelWidth(inputLabel.current.offsetWidth);}, []);
const [state, setState] = React.useState({
hostname: {
value: "test",
isError: false,
errorText: "",
},
serverIp: {
value: "192.168.16.1",
isError: false,
errorText: "",
},
osVariant: {
value: "Linux",
isError: false,
errorText: "",
},
databaseSid: {
value: "mysql",
isError: false,
errorText: "",
},
listenerPort: {
value: "3306",
isError: false,
errorText: "",
},
isFormValid: true,
isPrimaryDbValid: false,
});
const evaluateFormValid = (prevState) => {
return ((prevState.hostname.value!=="" && !prevState.hostname.isError) &&
(prevState.serverIp.value!=="" && !prevState.serverIp.isError) &&
(prevState.osVariant.value!=="" && !prevState.osVariant.isError) &&
(prevState.databaseSid.value!=="" && !prevState.databaseSid.isError) &&
(prevState.listenerPort.value!=="" && !prevState.listenerPort.isError));
};
const handleChange = event => {
var valResult;
switch (event.target.id) {
case 'hostname':
valResult = PrimaryFormValidator.validateHostname(event.target.value, event.target.labels[0].textContent);
setState({
...state,
hostname:
{
value: event.target.value,
isError: valResult.isError,
errorText: valResult.errorText,
},
});
break;
case 'serverIp':
valResult = PrimaryFormValidator.validateIpAddress(event.target.value, event.target.labels[0].textContent);
setState({
...state,
serverIp:
{
value: event.target.value,
isError: valResult.isError,
errorText: valResult.errorText,
}
});
break;
case 'databaseSid':
valResult = PrimaryFormValidator.validateDatabaseSid(event.target.value, event.target.labels[0].textContent);
setState({
...state,
databaseSid:
{
value: event.target.value,
isError: valResult.isError,
errorText: valResult.errorText,
}
});
break;
case 'listenerPort':
valResult = PrimaryFormValidator.validateListenerPort(event.target.value, event.target.labels[0].textContent);
setState({
...state,
listenerPort:
{
value: event.target.value,
isError: valResult.isError,
errorText: valResult.errorText,
}
});
break;
default:
//setState({...state,});
}
setState(prevState => ({
...prevState,
isFormValid: evaluateFormValid(prevState),
}));
}
const handleTestConnection = event => {
APIManager.testConnection(state.hostname.value, state.serverIp.value, state.osVariant.value, state.databaseSid.value, state.listenerPort.value);
//console.log("Data:" + APIManager.state.testConnectionResult);
}
const handleSelect = osVariant => event => {
var valResult = PrimaryFormValidator.validateOsVariant(event.target.value, inputLabel.current.textContent);
setState(prevState => ({
...prevState,
osVariant:
{
value: event.target.value,
isError: valResult.isError,
errorText: valResult.errorText,
},
}));
setState(prevState => ({
...prevState,
isFormValid: evaluateFormValid(prevState),
}));
}
return (
<React.Fragment>
<div className={classes.bigContainer}>
<Paper className={classes.paper}>
<div>
<div>
<Typography variant="subtitle1" gutterBottom className={classes.subtitle1} color='secondary'>
Primary Database System
</Typography>
<Typography variant="body1" gutterBottom>
Information related with the primary database system. Please note that the primary database has to be up and running.
</Typography>
</div>
<div className={classes.bigContainer}>
<form className={classes.formArea}>
<TextField className={classes.formControl}
id="hostname"
label="FQDN Hostname *"
onChange={handleChange}
value={state.hostname.value}
error={state.hostname.isError}
helperText={state.hostname.errorText}
variant="outlined" autoComplete="off" />
<TextField className={classes.formControl}
id="serverIp"
label="Server Ip Address *"
onChange={handleChange}
value={state.serverIp.value}
error={state.serverIp.isError}
helperText={state.serverIp.errorText}
variant="outlined" autoComplete="off" />
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel id="osVarLabel" htmlFor="osVariant" ref={inputLabel}>OS Variant *</InputLabel>
<Select
id="osVariant"
label="OS Variant *"
value={state.osVariant.value}
error={state.osVariant.isError}
onChange={handleSelect("osVariant")}
input={<OutlinedInput id="outlinedinput" labelWidth={labelWidth}/>}>
<MenuItem value={''}></MenuItem>
<MenuItem value={'Linux'}>Linux</MenuItem>
<MenuItem value={'Windows'}>Windows</MenuItem>
</Select>
<FormHelperText error={state.osVariant.isError} hidden={!state.osVariant.isError}>
{state.osVariant.errorText}
</FormHelperText>
</FormControl>
<TextField className={classes.formControl}
id="databaseSid"
label="Database SID"
onChange={handleChange}
value={state.databaseSid.value}
error={state.databaseSid.isError}
helperText={state.databaseSid.errorText}
variant="outlined" autoComplete="off" />
<TextField className={classes.formControl}
id="listenerPort"
label="Listener Port"
onChange={handleChange}
value={state.listenerPort.value}
error={state.listenerPort.isError}
helperText={state.listenerPort.errorText}
variant="outlined" autoComplete="off" />
{/* <TextField className={classes.formControl}
disabled={true}
id="isFormValid"
label="Is Form Valid Now?"
value={state.isFormValid}
variant="outlined" autoComplete="off" /> */}
</form>
</div>
</div>
</Paper>
<Grid container spacing={2} className={classes.grid}>
<Grid item xs={12}>
<div className={classes.flexBar}>
<Tooltip title="Back to previous step">
<div>
<Button variant="contained"
disabled={true}
className={classes.actionButton}
size='large'>
<BackIcon className={classes.rightIcon}/>Back
</Button>
</div>
</Tooltip>
<Tooltip title="Test Connection">
<div>
<Button variant="contained" className={classes.actionButton}
color="primary"
size='large'
disabled={!state.isFormValid}
onClick={handleTestConnection}>
<TestIcon className={classes.rightIcon}/>Test
</Button>
</div>
</Tooltip>
<Tooltip title="Proceed the next step">
<div>
<Button
variant="contained" className={classes.actionButton}
color="primary"
size='large'
disabled={!state.isPrimaryDbValid}>
<ForwardIcon className={classes.rightIcon} />Next
</Button>
</div>
</Tooltip>
<Tooltip title="Cancel creating new configuration">
<Button variant="contained" color="default" className={classes.actionButton}
component={Link} to={'/configs'} style={{ marginLeft: 'auto' }}>
<CancelIcon className={classes.rightIcon} />Cancel
</Button>
</Tooltip>
</div>
</Grid>
</Grid>
</div>
</React.Fragment>
)
}
export default withRouter(withStyles(styles)(PrimaryForm));
这是我的经理。js文件:
import React, { Component } from 'react';
export default class APIManager extends Component{
constructor(props) {
super(props);
this.state = {
testConnectionResult: {},
...this.props,
}
this.testConnection = this.testConnection.bind(this);
}
static testConnection(hostname, serverIp, osVariant, databaseSid, listenerPort) {
fetch(`http://localhost:8000/api?objtype=ConnectionDef&hostname=${hostname}&serverIp=${serverIp}&osVariant=${osVariant}&databaseSid=${databaseSid}&listenerPort=${listenerPort}`)
.then(response => response.json())
.then(result => this.setState({testConnectionResult: result}));
//.catch((error) => console.error(error));
console.log("Data:" + this.testConnectionResult);
return this.testConnectionResult;
}
}
现在我无法解决下面的错误:
经理。js:16未捕获(promise中)类型错误:_this2。setState不是APIManager的函数。js:16
我想我现在很难将API调用的结果传递给外部(被调用方)类/函数。
我谷歌了一下,还检查了Stackoverflow上的其他问题,但这并没有帮助我解决这个问题。我还想问我是否犯了一个主要错误。
任何帮助都将不胜感激。谢谢。
您不必仅仅为了保存API调用逻辑而创建组件。in-react组件用于声明可视内容(因此它们将具有jsx)。
若要从组件中提取api调用逻辑,可以将该逻辑放入某个返回promise的函数中。像这样:
function testApi(...args) {
return fetch(/* url parms */)
}
然后在你的组件中,在某个事件中,比如单击,你可以调用应用编程接口,并将响应数据设置为组件状态以更改视图:
handleTestEvent(...args) {
testApi(...args)
.then(response => response.json())
.then(result => this.setState({testConnectionResult: result}));
.catch((error) => {
console.error(error));
this.setState({testConnectionResult: []});
});
}
您不能从静态方法访问此(实例上下文)。让它成为一个常规的实例方法,它应该可以工作。
在5.1版本中,大部分的助手函数都可以归结为一个函数app(),因为5.1全面采用容器管理类的实例,而app()函数又是容器的“管家”。 助手函数 系统为一些常用的操作方法封装了助手函数,便于使用,包含如下: 助手函数 描述 abort 中断执行并发送HTTP状态码 action 调用控制器类的操作 app 快速获取容器中的实例 支持依赖注入 behavior 执行某个行为 bind 快速绑定对象
问题内容: 几天以来,我一直在为我的实习机会创建一个React Web应用程序,但是遇到了CORS错误。我正在使用最新版本的reactJS,并将其放在中,以下是用于获取的代码: 抱歉,由于公司规定,我无法发布该API的网址,但是,可以确认该API后端中没有CORS设置。 但是,在mozilla上运行时遇到以下错误 和 如果在chrome上运行,则会出现以下错误 和 和 另一件事是,我可以在浏览器中
我正在创建一个电子学习网站,那里有你可以选择的课程卡片。这是我的密码 课程ist.vue 我的问题是我无法从API链接获取数据- 我想知道我做错了什么。我也尝试使用{{list}}来获取数据,但没有成功。我现在的目标是得到所有的数据,即使它看起来很乱。抱歉我英语不好,谢谢你!
我试图获取一系列api数据。根据下面的api数据,每个系列都有自己的数据,例如,一系列“bannerData”有自己的数据id,banner_title...下一个系列“home ecatData”有自己的数据,比如id,category_title...等等 在我的例子中,endpointapi是http://localhost:8000/api/homepage/ 如何在reactjs中获取这
我正在创建一个fetchBill函数。分配https://randomapi.com/api/006b08a801d82d0c9824dcfdfdfa3b3c到一个api变量。它使用浏览器的fetch函数向api发出HTTP请求。它在一个函数中使用箭头函数。然后调用fetch函数,并在将其转换为JSON后返回响应。使用另一个。然后调用第一个函数,该函数将JSON数据传递给displayCartTo