【问题标题】:How do I only render one result in a separate component using axios in React?如何在 React 中使用 axios 仅在单独的组件中呈现一个结果?
【发布时间】:2019-10-22 16:29:00
【问题描述】:

编辑//

我想我的问题不是很清楚。当我的 url 指向 http://localhost:1233/details/‘${parkcode}’ 时,我试图让一个公园返回。我在 results.js 文件中定义了 url 的参数。但是我在 details.js 中定义 this.setState 时遇到了麻烦,以仅根据 id 呈现公园的一个结果,这也恰好是公园代码。

我是 React 新手(可能是 JavaScript,我不知道了)。我正在关注一个教程 - 我决定分支并使用 axios.get() 从 API 获取数据,而不是使用 npm 包作为 API。我能够将组件的结果呈现到浏览器中,但是在添加到达路由器(我假设它类似于 React 路由器)之后,我无法将我的 API 调用的一个结果呈现为我尝试的页面build 应该只根据我定义的 ID 显示一个结果。

在我的主文件中,也就是这里的 Results.js,我能够毫无问题地获取数据,并使用 JSX 将它们包含在我的文件中并渲染它们。我正在尝试使用与我在 Details.js 页面中的该页面中所做的相同的逻辑(该页面应该只向路由中的 ID 显示一个结果)。

我如何在 Results.js 中使用 axios

componentDidMount() {
    axios
      .get(
        "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +
          `${nps}`
      )

      // https://css-tricks.com/using-data-in-react-with-the-fetch-api-and-axios/
      .then(res =>
        res.data.data.map(park => ({
          description: `${park.description}`,
          fullname: `${park.fullName}`,
          states: `${park.states}`,
          parkcode: `${park.parkCode}`,
          image: `${park.images[0] ? park.images[0].url : "No Image"}`,
          designation: `${park.designation}`
        }))
      )
      .then(parks => {
        this.setState({
          parks
        });
        console.log(parks);
      });
  }

我如何尝试在 Details.js 中使用相同的逻辑

即使我进行了 API 调用,它也无法识别 park.name。但是,如果我硬编码 park[0].name 它可以工作。我不知道我在这里做错了什么。这可能是一个明显的问题,但请帮助我。

class Details extends React.Component {
  constructor (props) {
    super(props);

    this.state = {
      loading: true,
    }
  }

  componentDidMount() {
    axios
      .get(
        "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +
          `${nps}`, 
          { id: this.props.id }

      ).then(res => {
        const park = res.data.data.map(park => ({
          description: `${park.description}`,
          fullname: `${park.fullName}`,
          states: `${park.states}`,
          parkcode: `${park.parkCode}`,
          image: `${park.images[0] ? park.images[0].url : "No Image"}`,
          designation: `${park.designation}`
        }))

        console.log(park.name);

        this.setState({
          name: park.name;
          loading: false
        })
      }).catch(err => {
        this.setState({error: err});
      })
  }

我希望页面能够识别 GET 请求中定义的 id 以及 axios,并呈现与 id 相关的公园详细信息。但是现在,它什么也没做,我一直被困在这上面:(

【问题讨论】:

  • 所以你试图在单击时显示单个项目的详细信息??
  • 是的!基本上来自我的Results.js,我在呈现所有结果后单击某个公园,它将链接到详细信息页面以显示一个公园的详细信息。
  • 看起来像您的 API 返回公园数组。像这样的东西:[{ name: "park1" }, { name: "park2" }]。如果您希望他们只返回单个公园,您的响应数据应如下所示{ name: "park1" }
  • 这里有一个与您尝试做的相同的教程codingthesmartway.com/…
  • @vedsmith92 我正在努力弄清楚如何将该部分写入 .then() 当我使用 axios 时它返回一个数组,但我正在努力让它只返回一个.. .

标签: reactjs axios state reach-router


【解决方案1】:

您的代码中有一些不必要的部分。您不需要像在 setState 部分中那样构建数据。您正在获取公园列表,它已经是结构化数据。因此,只需使用您返回的数据设置您的状态。

之后,您可以映射这些数据并使用 React Router 的链接渲染公园。您可以使用parkCode 作为Link 的URL 参数。在 Details 组件中,您可以提取此 parkCode 并提出新的公园详细信息请求,然后将其设置为您的状态。

我提供了一个例子。

index.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Results from "./Results";
import Details from "./Details";

const Routes = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Results} />
      <Route path="/details/:parkCode" component={Details} />
    </Switch>
  </Router>
);

ReactDOM.render(<Routes />, document.getElementById("root"));

结果

import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";

class Results extends React.Component {
  state = {
    parks: [],
    loading: true,
  };

  componentDidMount() {
    axios(
      "https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=LbqZVj21QMimfJyAHbPAWabFaBmfaTZtseq5Yc6t"
    ).then(res => this.setState({ parks: res.data.data, loading: false }));
  }

  renderParks = () =>
    this.state.parks.map(park => (
      <Link to={`/details/${park.parkCode}`} key={park.parkCode}>
        <div>{park.fullName}</div>
      </Link>
    ));

  render() {
    return (
      <div>{this.state.loading ? <p>Loading...</p> : this.renderParks()}</div>
    );
  }
}

export default Results;

详情

import React from "react";
import axios from "axios";

class Details extends React.Component {
  state = { park: "", loading: true };

  componentDidMount() {
    const { match } = this.props;
    axios(
      `https://developer.nps.gov/api/v1/parks?parkCode=${match.params.parkCode}&api_key=${nps}`
    ).then(res => this.setState({ park: res.data.data[0], loading: false }));
  }

  render() {
    return (
      <div>
        {this.state.loading ? <p>Loading...</p> : this.state.park.description}
      </div>
    );
  }
}

export default Details;

【讨论】:

    【解决方案2】:

    你可以在.then()试试这个

    let park = res.data.data.map(park => ({
        description: `${park.description}`,
        fullname:    `${park.fullName}`,
        states:      `${park.states}`,
        parkcode:    `${park.parkCode}`,
        image:       `${park.images[0] ? park.images[0].url : "No Image"}`,
        designation: `${park.designation}`
    }))
    park = park[0]; // convert arrays of parks to single park
    console.log(park.fullname); // now you can use `park.fullname`
    

    或者这个

    const park = {
        description: `${res.data.data[0].description}`,
        fullname:    `${res.data.data[0].fullName}`,
        states:      `${res.data.data[0].states}`,
        parkcode:    `${res.data.data[0].parkCode}`,
        image:       `${res.data.data[0].images[0] ? park.images[0].url : "No Image"}`,
        designation: `${res.data.data[0].designation}`
    }
    console.log(park.fullname); // now you can use `park.fullname`
    

    否则在 API 中执行

    【讨论】:

    • 谢谢!但我想我想做的是假设我的数据返回 10 个项目。如果我在访问一个元素时编码 [0],它不会对其他元素起作用吗?我正在尝试找到一种方法,当单击结果上的一个公园时,它会自动链接到正确的公园。该 API 不包含 id 参数,所以我认为这就是它难的原因。
    • 好的,试试这个let park = res.data.data.find(park =&gt; park.id === this.props.id).map(park =&gt; ({ 然后删除park = park[0];
    【解决方案3】:

    我认为您可以先为您的回复设置一个状态,然后尝试显示它们

    同样的:

    state = {
      result: []
    }
    
    componentDidMount() {
      axios
        .get("https://developer.nps.gov/api/v1/parks?stateCode=wa&fields=images&api_key=" +`${nps}`).then((res) => {
          this.setState({result: res.data.data})
      })
    }
    
    render(){
      const result = this.state.result.map((el, index) => {
        return(
          //data
        )
      })
      return(
         <div>
           {result}
         </div>
      )
    }
    

    【讨论】:

      【解决方案4】:

      我相信这是你弄错的部分

      const parks = res.data.data.map(park => ({
        description: `${park.description}`,
        fullname: `${park.fullName}`,
        states: `${park.states}`,
        parkcode: `${park.parkCode}`,
        image: `${park.images[0] ? park.images[0].url : "No Image"}`,
        designation: `${park.designation}`
      }))
      
      console.log(parks) // this should display your array of all parks
      
      this.setState({
        parks,
        loading: false
      })
      
      displayParks(parks) {
       const allParks = parks.map((park, index) => {
         return <div key={park.parkCode}>{park.fullname}<div>
       })
      }
      
      
      render() {
      const { parks } = this.state;
      
      const displayParks = parks && parks.length > 0 ? this.displayParks(parks) : <div>Loading parks</div>
        return (
            <div>{ displayParks }</div>
          );
        }
      

      当您对数组执行 .map 时,您基本上是在创建另一个数组,这就是返回给您的 park 变量的内容。

      因此,在您的渲染方法中,您可以循环遍历 parks 中的每个项目

      【讨论】:

      • 我也试过了。当我在 this.setState 中执行 name: park.name 时,它​​不会返回任何内容。当我把它带到我的渲染方法时,我无法访问状态。当我将其命名为:park[0].fullname 时,它​​就可以工作了。
      • 是的。你应该明白这一点,因为当你使用.map 时你正在创建一个数组。所以通常情况下,如果数组中只有一项,那么以数组中的索引位置为目标来获取值是有意义的
      • @CynthiaWong 我刚刚修改了代码。我希望这会有所帮助
      猜你喜欢
      • 1970-01-01
      • 2020-08-30
      • 2021-01-21
      • 2020-05-23
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多