【问题标题】:Fetch request inside function. How to put it in ComponentDidMount?在函数内部获取请求。如何将其放入 ComponentDidMount 中?
【发布时间】:2017-08-23 20:07:16
【问题描述】:

如您所见,我的 handleSearchRequest 函数正在调用一个 API,该 API 稍后由 IconButton 标记内的 onClick 事件调用。

如何在 ComponentWillMount 中加载 API,我仍然可以在 HandleSearchRequest 上写一些东西,比如 setState 或其他东西,这样 Onclick 仍然可以调用这个函数?

class Searcher extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      query: '',
      application: null
    }

  }

  // componentDidMount () {
  //
  //
  //
  // }

  handleSearchRequest() {
    console.log('this.state', this.state);
    const BASE_URL = 'https://itunes.apple.com/search?term';
    const FETCH_URL = BASE_URL + '=' + this.state.query;
    console.log('FETCH_URL', FETCH_URL);

    fetch(FETCH_URL, {
      method: 'GET'
    })

      .then(response => response.json())
        .then(json => {
          const application = json.results[0];
          this.setState({application})
          console.log({application})
        });
  }

  render () {
    return (
      <div style={{position: 'relative'}}>
           <IconButton
             iconStyle={styles.smallIcon}
             style={styles.iconButton}
             onClick={() => this.handleSearchRequest()}
           >
               <Search color={black} />
           </IconButton>
        <TextField
          underlineShow={false}
          id="searchId"
          value={this.state.query}
          fullWidth={true}
          style={styles.textField}
          inputStyle={styles.inputStyle}
          hintStyle={styles.hintStyle}
          onChange={event => {this.setState({ query: event.target.value}) }}
          onKeyPress={event => {
            if (event.key === 'Enter') {
              this.handleSearchRequest()
            }
          }}
        />
        <br/>
        <br/>
        {
          this.state.application !== null
          ?
            <ResultItem
              {...this.props} {...this.state}
              application={this.state.application}
            />
          : <div></div>
        }
      </div>
    );
  }
}
export default Searcher;

编辑

这是 ResultItem 组件

class ResultItem extends Component {

componentDidMount () {

}
  render () {
    // console.log ('myProps', this.props);

    let application = {
      artistName: '',
      country: '',
      primaryGenreName: '',
      trackName: ''
    };

    if (this.props.application !== null) {
      application = this.props.application
    }

    return (
      <div>

        <Card style={{width:'30%'}}>
          <CardMedia>
            <div style={styles.appCard}/>
          </CardMedia>
          <FloatingActionButton
            style={styles.addButton}
            backgroundColor={'#CC0000'}
            >
            <ContentAdd />
          </FloatingActionButton>
          <CardTitle
            title={application.artistName}
                     subtitle="Application" />
          <CardText>
            <div>
              <div>Name:   <b>{application.artistName}      </b> </div>
              <div>Country:<b>{application.country}         </b> </div>
              <div>Genre:  <b>{application.primaryGenreName}</b> </div>
              <div>Song:   <b>{application.trackName}       </b> </div>
            </div>
          </CardText>
        </Card>
    </div>
    );
  }
}

export default ResultItem; 

【问题讨论】:

  • 不记得是什么意思?
  • 就像,如果我将函数的所有内容都放在 ComponentDidMount 中。那么 handleSearchRequest 将只有 1 行 const application = json.result [0] ,但是这 2 个值(application 和 json)不是全局变量,你知道,就像在 ES5 中一样?无论如何,这样做是一种不好的做法
  • 当你想存储信息时,你使用 this.setState({ ... }) 将它存储在组件状态中。就这些。您可以使用 this.state.someProp 从任何组件方法访问状态
  • 我只是想像在这个反应模式的书 xzlearning.com/skills/6010 中那样实现它。正如你所看到的,他们在 ComponentDidMount 中有 fetch 调用,只是试图在那里应用模式
  • 从componentDidMount调用方法应该没有问题。你到底在纠结什么?

标签: json reactjs fetch


【解决方案1】:

生命周期方法componentDidMount 通常用于获取一些初始数据以供您的 React 组件使用。

给定一个发出 HTTP 请求以获取一些数据的方法。例如,

fetchData() {
  fetch('https://www.somewhere.com/someResource')
    .then(response => response.json())
    .then(responseJson => {
      this.setState({ someResource: responseJson });
    });
}

你可以使用 setState() 将数据保存到组件状态,如上所示,获取后。

然后简单地从componentDidMount() 调用它以使用初始数据填充您的组件状态:

componentDidMount() {
  this.fetchData();
}

您可以随时再次致电fetchData() 再次获取该数据。

要从任何组件方法(如在 render() 中)访问资源,请使用 this.state.someResource

更新:

如果您有一个依赖数据进行自身渲染的组件,那么您应该小心。最初不会有数据,因此如果该组件依赖于该数据,则不应渲染该组件,如果该组件不存在则会出错。

解决方案是在渲染之前检查数据是否存在。

示例

render() {
  if (!this.props.someResource) {
    // resource is not yet loaded
    return <div>Loading resource...</div>;
  }

  // Otherwise, if someResource has been fetched (i.e. is not undefined)
  // You can safely render the component that is dependent on it
  return (
    <MyComponent someResource={this.props.someResource} />
  );
}

【讨论】:

  • 我以前试过。我收到一条无法读取未定义消息的属性“艺术家姓名”。您的答案的重要部分是有道理的,但我该如何复制它们?
  • 我刚刚点击了您的 API 端点,它返回了以下格式的对象:{ "resultCount":0, "results": [] }。在 componentDidMount 中调用 fetch 函数将使用空查询(因为在您的初始状态下,查询是 ''),这将导致该响应。数组results 没有元素,所以说const application = json.results[0]; 将导致未定义。所以你应该在用它实现任何东西之前考虑来自那个 API 的响应。
  • 我无法为您提供有关艺术家姓名部分的帮助,因为它不在问题范围内。听起来您正在尝试访问不存在的东西。这是有道理的,因为我之前的评论说您查询了 API 但没有得到任何结果。如果您确实有任何数据要渲染,您应该始终确保检查您的渲染函数。如果不是,则不要尝试显示依赖于现有数据的某些组件。请参阅我的答案的更新
  • 是的,如果我把函数放在 ComponentDidMount 里面是有道理的,那就是问题开始了,查询的值是 ' ' (empty string) ,这应该是因为这是一个搜索输入框的值永远是空的。所以我想不把它放在 ComponentDidMount 上是有道理的?..但是我觉得我可以以某种方式将 this.state.application 的值放在我的渲染函数中,但是如何?...我需要担心this.state.query 也是?...我已经编辑了我的问题,所以你可以看到 artistName 的东西
  • 查看更新后的答案,如果 this.props.application 的值未定义,this.props.application !== null 行将是真的。因此,您正在做application = undefined,这会导致您的错误。您可以通过两种方式解决此问题: (1) 只需执行this.props.application != null,因为undefined != null 将是错误的。 (2) 将if (this.props.application !== null) 替换为if (this.props.application),因为未定义的计算结果为假。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 2012-02-10
  • 2020-12-12
  • 2020-08-13
  • 2016-03-29
  • 1970-01-01
相关资源
最近更新 更多