【问题标题】:How to pass a function to each mapped items from an array?如何将函数传递给数组中的每个映射项?
【发布时间】:2021-11-17 04:21:26
【问题描述】:

在一个组件上,我映射了来自 API 的数组中的每个项目,并以 <li> 每个返回它们,如下所示:

const usersComponent = usersData.map((user: any) => (
      <li
        key={user.Username}
        className="px-4 my-2 lg:pl-8 w-full scale-95 transform transition duration-500 hover:scale-100"
      >
      \\ rest of the code

然后,在组件上,我这样做:

return (
  <ul>{usersComponent}</ul>
)

现在,此列表中的每个项目都是我的 API 中的 username,这些用户名在我的数据库中有组,但这些组仅从 API 的另一个 GET 中返回,我在另一个函数中拥有该组:

async function listGroupsForUser(username: string) {
    const apiName = 'AdminQueries'
    const path = '/listGroupsForUser'
    const myInit = {
      body: {
        username
      }, 
      headers: {
        'Content-Type': 'application/json',
        Authorization: `${(await Auth.currentSession())
          .getAccessToken()
          .getJwtToken()}`,
      },
    }
    return await API.get(apiName, path, myInit)
  }

所以,我需要为我映射的每个 &lt;li&gt; 传递这个 listGroupsForUser,然后它将为每个人返回一个数组,我需要为每个人单独映射它。

我尝试了很多方法,但都做不到。

【问题讨论】:

  • 您可以将map 中的单个项目设为它自己的React 组件,然后在该组件中您可以发出listGroupsForUser 请求,并相应地填写HTML。
  • 您能详细说明一下吗?如果我理解正确,我会在另一个文件中创建一个 组件,使用 props.username,然后在其中,我像这样传递函数:listGroupsForUser(username),对吗?
  • 这里有一个简单的例子来说明这个概念:codesandbox.io/s/sleepy-resonance-jo48b?file=/src/UserList.tsx
  • 如果列表中显示了 50 个用户,您是否为组进行了 50 次 API 调用?
  • @SamuelGoldenbaum 是的,这真是太糟糕了,这个 API 太糟糕了,它是 AWS Amplify 中 AdminQueries 的其余 API。如果listUsers GET 请求将为用户返回组,那将使我的生活更轻松,因为组将在第一个数组 im 映射中返回,但事实并非如此。所以我必须从这个listGroupsForUser GET 请求中获取每个组。

标签: javascript arrays reactjs typescript array-map


【解决方案1】:

取决于您是否需要预先获取所有数据,或者是否可以异步获取组。

要提前获取它们,您可以使用 Promise.All 并并行触发查询,例如:

const getRandomDelay = (min: number, max: number): number => {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1) + min);
};

// mock API call
const fetchGroups = (username: string): Promise<string[]> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      return resolve(['admin', 'editor']);
    }, getRandomIntInclusive(2000, 4000));
  });
};

const data = ['darth', 'fett', 'luke'];

interface User {
  name: string;
  groups?: string[];
}

export default function App() {
  const [users, setUsers] = useState<User[] | null>(null);

  useEffect(() => {
    Promise.all(
      data.map(async (user) => {
        const groups = await fetchGroups(user);
        return {
          name: user,
          groups: groups
        };
      })
    ).then((result) => {
      setUsers(result);
    });
  }, []);

  return (
    <div className="App">
      {users &&
        users.map((user) => (
          <div key={user.name}>
            {user.name}&nbsp;
            {user.groups.map((group) => (
              <span key={group}>{group}, </span>
            ))}
          </div>
        ))}
    </div>
  );
}

或者,您可以在每个中使用一个钩子。比如:

const useListGroupsForUser = (username: string) => {
  const [groups, setGroups] = useState<string[] | null>(null);

  useEffect(() => {
    console.info(`mocking fetch for ${username}`);
    fetchGroups(username).then((result) => setGroups(result));
  }, [username]);

  return {
    groups
  };
};

// User component
const User = ({ user }: UserProps) => {
  const { groups } = useListGroupsForUser(user);

  return (
    <li>
      {user} <br />
      {groups ? groups.map((group) => group) : <span>loading groups...</span>}
    </li>
  );
};

// and render in App
{data.map((user) => (
    <User key={user} user={user}/>
))}

【讨论】:

    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    相关资源
    最近更新 更多