【问题标题】:Can I use currying in React to make a subsequent API calls?我可以在 React 中使用柯里化来进行后续的 API 调用吗?
【发布时间】:2020-02-10 21:18:47
【问题描述】:

我正在尝试使用 PokeAPI 在 React 中制作 Pokemon 卡片。我希望卡片有 2 个侧面,一个正面和一个背面,并带有扩展的细节。由于 API 端点的工作方式,每个单独的 Pokemon 都必须调用其特定的端点以获取扩展的详细信息。现在我正在使用初始 api 调用(在 componentDidMount 内部)设置状态,它返回一个不详细的 pokemon 列表,包括它们的名称和 API 端点 url。此状态存储在名为“Cardcontainer”的基于类的容器中,该容器具有 2 个功能组件,“frontCard”和“backCard”,它们使用道具呈现。 backCard 数据通过点击事件的 HTTP 请求在 Cardcontainer 组件上检索,卡片将被翻转,显示详细信息。一切正常,但我无法将详细信息转到正确的卡上。我可以使用柯里化来解决我的问题吗?无论如何,我想保留我当前的设计,但是我可以使用柯里化来获取 componentDidMount 方法中的所有细节吗?你将如何解决这个问题?

卡片容器:

import React, { Component } from 'react';
import Frontcard from '../Components/frontCard';
import Backcard from '../Components/backCard';

class Cardcontainer extends Component {
state= {
    pokemon: [],
    cardBack: []
}

componentDidMount() {
        const xhr = new XMLHttpRequest();
        const url = 'https://pokeapi.co/api/v2/pokemon';

        xhr.onload = () => {
            if(xhr.status === 200) {
                const data = JSON.parse(xhr.responseText);
                const pokeList = data.results;
                this.setState(
                    {   ...this.state,
                        pokemon: pokeList,

                    }
                )
            } 
            else {
                console.log('not ok')
            }
        }

        xhr.open('GET', url, true);
        xhr.send();           
}

handleClick = (e) => {
    const xhr = new XMLHttpRequest();
    const url = `https://pokeapi.co/api/v2/pokemon/${e.currentTarget.firstChild.innerText}`;

    xhr.onload = () => {
        const backData = JSON.parse(xhr.responseText);
        const joined = this.state.cardBack.concat(backData)
        this.setState(
            {
                ...this.state,
                cardBack: joined
            }

        );
    }


    xhr.open('GET', url, true);
    xhr.send();
}

render() {

    return (
        this.state.pokemon.map((poke, index)=>{
            return (
                <div onClick={this.handleClick} 
                    className={"card-container"} 
                    key={index}
                    >
                    <Frontcard name= 
 {this.state.pokemon[index].name}/>
                    <Backcard frontName= 
 {this.state.pokemon[index].name} number={index} name= 
 {this.state.cardBack[index]} />
                </div>
            )
        })
    )
}


}

export default Cardcontainer;

背卡:

import React from 'react';

const Backcard = (props) => {
const details = props;
console.log(!details.name? 'hi':details.name.name)
console.log()

return (
    <div className={"card-back"}>  
        <h4>{details.name!==props.frontName? 'hi': 
details.name.name}</h4>
    </div>
)
}

export default Backcard;

【问题讨论】:

  • 这里有很多事情我会做不同的事情。我认为柯里化不会对您有所帮助,但是可能会将 api 调用移动到特定于卡的组件中,而不是在容器中进行。还要查看新的fetch api,而不是直接使用 xhr。如果我有时间,我可以快速模拟一下我将如何构建它
  • @david 我将数据存储在不同的容器中没有任何问题,可以让每张卡进行 api 调用吗?这不是不好的做法,因为真正需要显示数据的唯一元素是被翻转的元素?这就是为什么我试图在点击上提出请求,但我正在学习,但并不真正知道。
  • 这里有一些供你玩的东西:jsfiddle.net/t2udky8f 点击名称会将他们的类型添加到“卡片”中

标签: javascript reactjs currying


【解决方案1】:

如果我正确理解了您的问题,那么每个口袋妖怪特定数据(您在 backcard 组件中显示的数据)都有一个端点。

如果你真的不想对你的 React 组件做任何改变,你应该通过调用组件中的 n-times 来提供 this.state.cardback 数组,然后调用每个 pokemon 的每个特定端点(坏主意)首先检索 pokemon 列表,从中获取每个 pokemon 的后续 url。

我的建议是将数据保存在 Cardback 组件本身中,因此它有自己的状态,您将 url 作为 prop 传递,然后在 Cardback 组件中的 componentDidMount 方法中获取相应的数据。

【讨论】:

  • 你能在功能组件内部使用生命周期方法吗?我可以将 url 传递给 backCard,并使用它进行调用,并通过从容器组件作为 prop 传递的函数填充状态吗?
  • 是的,你可以,使用 React Hooks 你不再需要使用类。但是,如果您不想更改当前的方法,只需将 backCard 设为有状态组件而不是功能组件即可。
【解决方案2】:

我不确定您所说的使用柯里化是什么意思。 Currying 是一个函数返回另一个函数的概念,该函数可以在不同的时间点执行,它具有父函数变量的快照。

说到你的问题,在同一个组件中获取组件所需的数据是个好主意。您应该将 Pokemon id 或 url 传递给 backCard 组件,并在那里执行 REST 调用,以使用钩子获取数据并填充组件。

我刚刚检查了https://pokeapi.co/api/v2/pokemon api,你可以将 URL 作为 prop 传递给 backCard 组件吗?

卡片容器:

import React, { Component } from 'react';
import Frontcard from '../Components/frontCard';
import Backcard from '../Components/backCard';

class Cardcontainer extends Component {
state= {
    pokemon: [],
    cardBack: []
}

componentDidMount() {
        const xhr = new XMLHttpRequest();
        const url = 'https://pokeapi.co/api/v2/pokemon';

        xhr.onload = () => {
            if(xhr.status === 200) {
                const data = JSON.parse(xhr.responseText);
                const pokeList = data.results;
                this.setState(
                    {   ...this.state,
                        pokemon: pokeList,

                    }
                )
            } 
            else {
                console.log('not ok')
            }
        }

        xhr.open('GET', url, true);
        xhr.send();           
}



render() {

    return (
        this.state.pokemon.map((poke, index)=>{
            return (
                <div            className={"card-container"} 
                    key={index}
                    >
                    <Frontcard name= 
 {this.state.pokemon[index].name}/>
                    <Backcard frontName= 
 {poke.name} number={index} name= 
 {poke.name} url={poke.url} />
                </div>
            )
        })
    )
}


}

export default Cardcontainer;

背面卡片

    import React, { useState, useEffect }  from 'react';

    const Backcard = (props) => {

const [data, setData] = useState({});
  useEffect(() => {
    const xhr = new XMLHttpRequest();
    xhr.onload = () => {
        const backData = JSON.parse(xhr.responseText);
        const joined = this.state.cardBack.concat(backData)
        setData(joined);
    }
    xhr.open('GET', this.props.url, true);
    xhr.send();

  }, []);

    const details = props;
    console.log(!details.name? 'hi':details.name.name)
    console.log()

    return (
        <div className={"card-back"}>  
            <h4>{details.name!==props.frontName? 'hi': 
    details.name.name}</h4>
        </div>
    )
    }

    export default Backcard;

【讨论】:

  • 是的,我可以通过我刚刚意识到的道具传递 URL。我可以那样做,没有钩子吗?我只是在没有它们的情况下学习了 React,并且只想完成这个项目,并在学习新方法之前掌握我所学到的东西。我计划在完成此操作后学习钩子,并使用它们重写它,感谢 Redux,您的回答对我下一步的工作非常有帮助,让我知道该怎么做。
  • 我已经这样做了,并且得到了正确的信息,如果你按顺序点击它们,它工作正常。问题是我的初始数组是空的,所以说如果你先点击 Charizard(#9),他的数据会转到 Bulbasaurs(#1) 卡背面,而不是 Charizards div,因为这样 Charizard 是 cardback 数组中的第一个,并将道具映射到 #1 的 Bulbasaur,因为那是 Bulbasaur 从中获取数据的合乎逻辑的地方。我可以只用空对象填充一个数组,然后将它们拼接到正确的位置,还是状态下的填充方法会覆盖所有内容?
猜你喜欢
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 2022-11-22
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
相关资源
最近更新 更多