首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在react中呈现有关支柱更改的返回数据

如何在react中呈现有关支柱更改的返回数据
EN

Stack Overflow用户
提问于 2018-05-22 18:10:16
回答 2查看 1.2K关注 0票数 0

我很难弄清楚如何让API调用重新呈现到屏幕上。我有一个apiCall函数,它传递this.state并通过传递的ref更改状态,但它不会触发道具更改上的重登。

searchBody.js

代码语言:javascript
复制
 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

methods.js

代码语言:javascript
复制
// 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
      })


}

我是不是把代码构造错了?我的理解是,当道具改变时,它会强制重呈现。我应该把"this.state.apiData“传递给apiCall而不是这样的整个州吗?

代码语言:javascript
复制
apiCall(this.state.apiData)

这是在componentDidMount()中运行的,我相信这是调用API的正确位置,但回调时不会重新呈现。我可以在调试器中看到状态变量正在按预期更新。我是否应该在apiCall()中设置一个返回变量,并让返回值更新componentDidMount()中的状态?一旦数据被返回,这会强制重新呈现吗?

像这样吗?

代码语言:javascript
复制
this.setState({apiData: apiCall()})

如果我从this.state.apiData ()返回apiCall()并让它解析apiCall中的表头和行,当状态变量被返回时,这会强制更新吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-22 19:24:10

埃里克·哈塞尔布莱帮我找到了这个答案。我调用了apiCall(),它在componentDidMount中没有返回任何内容。我在methods.js apigClient.invokeAPI()之前添加了返回,这样它将返回函数的结果

代码语言:javascript
复制
  return 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)
          debugger
          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
      })

然后,我将函数调用从SearchBody.js内部更新为

代码语言:javascript
复制
componentDidMount() {
  console.log('Inside compDidMount')
  if (this.state.urlSearchTerm){
      apiCall(this.state).then(apiResponse => this.setState({
        loaded: true,
        apiData: apiResponse
      })
    )
  }
 }

因此,现在apiCall返回一个诺言的结果,而由于添加了.then函数,apiCall现在是一个允诺。这允许在componentDidMount中更改状态,从而使react看到有一个道具更改并重新呈现。

票数 0
EN

Stack Overflow用户

发布于 2018-05-22 18:49:14

您正在运行一个异步调用来获取一些rest数据。从定义上说,异步意味着您不知道您的代码何时会完成。这意味着您需要在apiCall完成后运行某种类型的回调。

这里有一个rest调用,它返回一个promise对象。承诺对象基本上是一个接口,用于向异步代码添加回调。我建议您在restApi调用之后使用以下选项之一来运行回调。

1.)可以将回调函数作为第二个参数传递给restApi()。您将以这样的方式调用此回调:

代码语言:javascript
复制
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调用创建的承诺来处理apiCall的解析。当您执行异步代码时,对异步方法的调用立即返回诺言对象,您可以返回到调用函数,以允许调用者附加回调。这听起来可能有点令人困惑,我不是最擅长解释事情的人,但我看到了以下几点:

代码语言:javascript
复制
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()方法中附加任何回调功能。

最终,您希望确保当setState数据实际返回到调用者时,您正在调用restApi。.then()是触发该调用并可靠地获得返回结果的最简单方法。

注意:您还应该研究JS中的承诺,因为.then方法可以接受2个参数,一个函数处理数据的成功返回,另一个函数处理错误报告。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50474012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档