0
getLinkName(segments) {
    let arr = segments.split('/') // cars/honda
    let el = []
    let baseUrl = arr[0]
    arr.map(async (item, index) => {
        let name = await getCategoryNameFromSlug(baseUrl)
        baseUrl = baseUrl + '/' + arr[index]
        let i = (
            <Link to={'/' + baseUrl} key={index}>
                {name}
            </Link>
        )
        el.push(i)
    })
    console.log('el', el)
    return el
}

我得到了这个函数,它遍历一个数组。在每个索引处。它获取数据,然后返回数据和一个反应元素。

问题,我期望的结果是一个反应元素数组,但我得到了一堆承诺

4

2 回答 2

0

这是意料之中的,因为这是异步 js 的工作方式,函数运行完成,所以当你的 getLinkName 函数返回时,你的 el arr 将有一堆承诺。

React 中的网络请求应该在 eventListeners 或生命周期组件上完成

假设您使用的是类组件,您的代码应该看起来像这样

// make sure babel supports this or set the initial state in the constructor
state = { categoryNames: null}

componentDidMount() {
    let  baseUrl = segments.split('/')[0]
 Promise.all(segments.split('/').map((item,index) => {
    let name = await getCategoryNameFromSlug(baseUrl)
    baseUrl = baseUrl + '/' + arr[index]
    return name;

})).then(categoryNames => this.setState({categoryNames}))
}



render(){
    // here use categoryNames like you wanted to do in your question

}
于 2019-09-13T05:46:48.000 回答
0

对于像您这样的情况,React中的一个常见模式是首先获取您的异步数据,然后将其保存为状态,这反过来又会触发您的组件的重新渲染。

React 元素是 React 查找更改时使用的基本构建块,并在每次触发渲染阶段时创建(例如render,类组件中的方法)。作为其内部差异算法实现的一部分, React 可能会调用render多次,因此您最好不要在渲染阶段依赖异步操作——它需要一个同步的返回值。

您可以像这样为类组件实现它:

class ExampleComp extends React.Component {
  state = { nameBaseUrlTuples: [] };

  componentDidMount() {
    this.getLinkName("cars/honda");
  }

  render() {
    return this.state.nameBaseUrlTuples.map((nameBaseUrlTuple, index) => (
      <Link to={"/" + nameBaseUrlTuple[1]} key={index}>
        {nameBaseUrlTuple[0]}
      </Link>
    ));
  }

  async getLinkName(segments) {
    const arr = segments.split("/"); // cars/honda
    let baseUrl = arr[0];
    const nameBaseUrlTuples = await Promise.all(
      // not sure, if you also want to iterate over first index
      // seems as first is your root path segment containing sub categories
      arr.map(async (item, index) => {
        let name = await getCategoryNameFromSlug(baseUrl);
        // You could remove this side effect by
        // using map callback's third "array" argument and
        // compose your URL with array.slice(0, index+1).join("/") or similar
        baseUrl = baseUrl + "/" + item;
        return [name, baseUrl];
      })
    );
    this.setState({ nameBaseUrlTuples });
  }
}
于 2019-09-13T05:38:58.947 回答