地图内 React 中渲染方法中的 API 调用

IT技术 node.js reactjs render
2021-05-06 15:45:33

我有一个userId数组,我需要显示与该数组相关的名称列表。我想在render方法内调用 API 调用并获取用户名。但这行不通。我该如何解决这个问题?

下面是我的render方法:

render(){
    ...
    return(
        <div>
            {this.state.users.map(userId => {
                return (
                    <div> {this.renderName(userId )} </div>
                )
            })}
        </div>
    )
    ...
}

下面是renderName函数:

renderName = (userId) => {
    axios.get(backendURI.url + '/users/getUserName/' + userId)
         .then(res => <div>{res.data.name}</div>)
}
4个回答

基本上你不能在渲染中使用异步调用,因为它们返回一个无效的 JSX 的 Promise。而是使用 componentDidMount 和 setState 用他们的名字更新用户数组。

通常,您不会直接在渲染方法中更改状态或获取数据。状态总是由动作/事件(点击、输入或其他)改变。每次 prop/state 改变时都会调用 render 方法。如果直接在渲染方法中更改状态,最终会陷入无限循环。

您应该使用生命周期方法或钩子从 api 加载数据。这是官方 React FAQ 中的一个示例:https : //reactjs.org/docs/faq-ajax.html

这不会呈现任何内容,因为 API 调用是异步的,并且由于renderName函数不返回任何内容,它将返回 undefined。

您应该创建一个函数,它将为所有用户 ID 调用 api 并更新状态

getNames = () => {
    const promises = [];
    this.state.users.forEach((userId) => {
        promises.push(axios.get(backendURI.url+'/users/getUserName/'+userId));
    })

    // Once all promises are resolved, update the state
    Promise.all(promises).then((responses) => {
        const names = responses.map((response) => response.data.names);
        this.setState({names});
    })

}

现在,只要有数据可用您就可以在componentDidMount或 中调用此函数componentDidUpdateusers

最后,您可以直接迭代名称并渲染它们

<div>
  {this.state.names.map((name) => {
    return <div> {name} </div>;
  })}
</div>

您可以将用户名设为自己的组件:

const request = (id) =>
  new Promise((resolve) =>
    setTimeout(resolve(`id is:${id}`), 2000)
  );
const UserName = React.memo(function User({ userId }) {
  const [name, setName] = React.useState('');
  React.useEffect(() => {
    //make the request and set local state to the result
    request(userId).then((result) => setName(result));
  }, [userId]);
  return <div> {name} </div>;
});
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [1, 2],
    };
  }
  render() {
    return (
      <ul>
        {this.state.users.map((userId) => (
          <UserName key={userId} userId={userId} />
        ))}
      </ul>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>