- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我无法弄清楚如何获取 API 调用以重新渲染到屏幕。我有一个 apiCall 函数,它传递 this.state 并通过传递的 ref 更改状态,但它不会触发 Prop 更改的重新渲染。
searchBody.js
class SearchBody extends Component {
constructor(props) {
super(props)
const queryString = require('query-string');
const queryTerm = queryString.parse(this.props.location.search);
this.state = { urlSearchTerm: queryTerm.search,
searchTerm: '',
loaded: false,
buttonClicked: null,
apiData: [],
tableHeaders: [],
tableRows: []
}
// check if URL has search term if so pass term for apiCall
if (this.state.urlSearchTerm) {
this.state.searchTerm = this.state.urlSearchTerm
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
// capture input text field to state variable
handleChange = searchTerm => event => {
this.setState({ searchTerm: event.target.value })
//console.log(this.state.searchTerm)
}
// handle form submission
handleSubmit = (event) => {
console.log('Inside HandleSubmit')
console.log('button clicked update url to /?search=' + this.state.searchTerm)
this.props.history.push('/?search=' + this.state.searchTerm);
this.setState({buttonClicked: true})
event.preventDefault();
}
// load search from API if search term is in URL
componentDidMount() {
console.log('Inside compDidMount')
if (this.state.urlSearchTerm){
this.setState({apiData: apiCall(this.state)})
}
}
render() {
const { classes } = this.props;
let table = ''
//check if API has loaded data and show results if true
if (this.state.loaded){
if (this.state.apiData.length === 0 && this.state.buttonClicked){
table = 'No Results Found'
//reset search button State
this.setState({buttonClicked: false})
} else {
table = <TableData tableHead={this.state.tableHeaders} tableData={this.state.tableRows} />
//reset search button State
this.setState({buttonClicked: false})
}
}
return (
<Fragment>
<hr/>
<form /*className={classes.container}*/ noValidate autoComplete="off" onSubmit={this.handleSubmit} >
<TextField
id="search"
label="Search field"
type="search"
/* className={classes.textField}*/
margin="normal"
onChange={this.handleChange('search')}
/>
<Button color='primary' letiant="outlined" type="submit" >Search DB</Button>
</form>
<h1>Results: </h1>
{table}
</Fragment>
)
}
}
export default SearchBody
方法.js
// break API data into arry of data for table component rows.
export const parseTableHeaders = input => {
// console.log(input)
if (input !== undefined && input.length !== 0) {
let head = []
for(let key in input[0]){ head.push(key);}
//console.log(head)
return head
}
}
///break API data into array of headers for table component
export const parseTableRows = (input) => {
let rows = [];
for(let o in input) {
rows.push(Object.values(input[o]));
}
//console.log(head)
return rows
}
//get api data from AWS
export function apiCall(props) {
const searchTerm = props.searchTerm
let apigClientFactory = require('aws-api-gateway-client').default;
const config = {
//apiKey: 'xxxx',
invokeUrl:'https://xxxx.execute-api.us-east-2.amazonaws.com'
}
let apigClient = apigClientFactory.newClient(config);
let params = {
//This is where any header, path, or querystring request params go. The key is the parameter named as defined in the API
// userId: '1234',
search_keyword: searchTerm
};
// Template syntax follows url-template https://www.npmjs.com/package/url-template
let pathTemplate = '/beta/testDB'
let method = 'GET';
let additionalParams = {
//If there are any unmodeled query parameters or headers that need to be sent with the request you can add them here
headers: { },
queryParams: {
search_keyword: searchTerm
}
}
apigClient.invokeApi(params, pathTemplate, method, additionalParams)
.then(function(result){
//This is where you would put a success callback
console.log('apiCall Returned. searchTerm; ', searchTerm)
console.log(result)
props.loaded = true
props.tableHeaders = parseTableHeaders(JSON.parse(result.data))
props.tableRows = parseTableRows(JSON.parse(result.data))
return JSON.parse(result.data)
}).catch( function(result){
//This is where you would put an error callback
})
}
我的代码结构是否错误?我的理解是,当 Prop 发生变化时,它将强制重新渲染。我应该将“this.state.apiData”传递到 apiCall 而不是像这样的整个状态?
apiCall(this.state.apiData)
它在 componentDidMount() 中运行,我相信这是调用 API 的正确位置,但它不会在回调时重新渲染。我可以在调试器中看到状态变量正在按预期更新。我应该在 apiCall() 中设置返回变量并让返回值更新 componentDidMount() 中的状态吗?一旦返回数据,这会强制重新渲染吗?
类似这样的东西吗?
this.setState({apiData: apiCall()})
如果我从 apiCall() 返回 this.state.apiData 并让它解析 apiCall 中的表头和行,那么当返回状态变量时,这会强制更新吗?
最佳答案
您正在运行异步调用来获取一些剩余的 api 数据。根据定义,异步意味着您不知道代码何时完成。这意味着您需要在 apiCall 完成后运行某种类型的回调。
这里有一个 Rest api 调用,它返回一个 Promise 对象。 Promise 对象基本上是一个用于向异步代码添加回调的接口(interface)。我建议您采用以下选项之一在restApi 调用后运行回调。
1.) 您可以将回调函数作为第二个参数传递给restApi()。您可以这样调用此回调:
let that = this;
apiCall(props, function(result) {
that.setState({apiData: result});
});
export function apiCall(props, callback) {
...
apigClient.invokeApi(params, pathTemplate, method, additionalParams)
.then(function(result){
...
callback(result);
...
});
...
}
2.) 您的另一个选择是通过锁定 api 调用创建的 Promise 来处理 apiCall 的解析。当您执行异步代码时,对异步方法的调用会立即返回 Promise 对象,您可以将其返回到调用函数以允许调用者附加回调。这听起来可能有点令人困惑,我不是最擅长解释事情,但请参阅以下内容:
let that = this;
apiCall(props).then(function(result) {
that.setState({apiData: result});
});
export function apiCall(props) {
...
return apigClient.invokeApi(params, pathTemplate, method, additionalParams)
.then(function(result){
...
});
}
这里的主要区别是您将实际的异步调用返回到 apigClient.invokeApi。这允许任何调用 apiCall() 的人在 .then() 方法中附加任何回调功能。
最终,您要确保在restApi 数据实际返回调用方时调用setState。 .then() 是触发该调用并可靠地获取返回结果的最简单方法。
注意:您还应该研究一下 JS 中的 Promise,因为 .then 方法可以接受 2 个参数,一个处理数据成功返回的函数,一个处理错误报告的函数。
关于javascript - 如何在 react 中渲染 Prop 更改时返回的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50474012/
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!