0

这是我第一次从 API 获取数据,而且我对 React 还是很陌生。如果有人可以提供帮助,将不胜感激!

我无法访问表格行中的某些数据。我正在尝试通过单击该行来访问 name 属性。我想要的是通过单击特定行来复制名称属性。

此外,我useEffect一直在不停地获取数据。我试图更改依赖项,但无论我做什么,它都会继续这样做。我通过单击按钮将端点传递给 API。

另一件事是,当我获取数据时,我想访问数组成员的每个索引,但我尝试过但无法弄清楚。所以我只访问index[1]resp.guild.members[1].characters)。

我的代码:

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

const Tabledata = ({ guildName }) => {
  const [members, setMembers] = useState([]);
  const [membersOnline, setMembersOnline] = useState([]);

  useEffect(() => {
    fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
      .then((res) => res.json())
      .then((resp) => {
        console.log(resp);
        setMembers(resp.guild.members[1].characters);
        setMembersOnline(() =>
          members.filter((player) => player.status !== "offline")
        );
      })
      .catch((err) => console.log(err));
  }, [members, guildName]);

  return (
    <div className="container">
      <h1>Enemies Online</h1>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th>Name</th>
            <th>Level</th>
            <th>Vocation</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {membersOnline.map((d, id) => (
            <tr
              key={d.id}
              onClick={(e) => {
                console.log(this.d.name);
                navigator.clipboard.writeText(`exiva "${e.target.value}`);
              }}
            >
              <td>{d.name}</td>
              <td>{d.level}</td>
              <td>{d.vocation}</td>
              <td>{d.status}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Tabledata;

代码工作:

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

const Tabledata = ({ guildName }) => {
  // const [members, setMembers] = useState([]);
  const [membersOnline, setMembersOnline] = useState([]);
  const [header, setHeader] = useState("");

  useEffect(() => {
    fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
      .then((res) => res.json())
      .then((resp) => {
        const members = resp.guild;
        setHeader(resp.guild.data.name);
        const allCharacters = members.reduce((accum, iter) => {
          accum.push(...iter.characters);
          return accum;
        }, []);
        console.log(members);
        console.log(allCharacters);
        setMembersOnline(() =>
          allCharacters.filter((player) => player.status !== "offline")
        );
      })
      .catch((err) => console.log(err));
  }, [guildName]);

  return (
    <div className="container">
      <h1>{header}</h1>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th>Name</th>
            <th>Level</th>
            <th>Vocation</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {membersOnline.map((d) => (
            <tr
              key={d.id}
              onClick={(e) => {
                navigator.clipboard.writeText(
                  `exiva "${e.currentTarget.children[0].innerText}`
                );
              }}
            >
              <td>{d.name}</td>
              <td>{d.level}</td>
              <td>{d.vocation}</td>
              <td>{d.status}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Tabledata;

但是,如果我尝试以某种方式将 resp.guild 分配给成员,则 reduce 将不起作用..像这样:


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

const Tabledata = ({ guildName }) => {
  const [members, setMembers] = useState([]);
  const [membersOnline, setMembersOnline] = useState([]);

  useEffect(() => {
    fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
      .then((res) => res.json())
      .then((resp) => {
        setMembers(resp.guild);
        setHeader(resp.guild.data.name);
        const allCharacters = members.reduce((accum, iter) => {
          accum.push(...iter.characters);
          return accum;
        }, []);
        setMembersOnline(() =>
          allCharacters.filter((player) => player.status !== "offline")
        );
      })
      .catch((err) => console.log(err));
  }, [members, guildName]);

  return (
    <div className="container">
      <h1>Enemies Online</h1>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th>Name</th>
            <th>Level</th>
            <th>Vocation</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {membersOnline.map((d, id) => (
            <tr
              key={d.id}
              onClick={(e) => {
                console.log(this.d.name);
                navigator.clipboard.writeText(
                  `exiva "${e.target.value.innerText}`
                );
              }}
            >
              <td>{d.name}</td>
              <td>{d.level}</td>
              <td>{d.vocation}</td>
              <td>{d.status}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Tabledata;

它会在reduce处抛出一个异常,说它不是一个函数

4

1 回答 1

0

我已经重构了您的代码,它在这里的代码沙箱中工作,呈现时没有错误。

在查看了您更新的问题并查看了您正在使用的 API 后,我做了一些更改。

  1. members我作为状态对象删除
  2. 我将 map 函数的键值设置为数组的索引,因为id它不是membersJSON 响应正文中的属性。
  3. members从依赖数组中删除,因为它不再是托管状态
  4. 我删除setHeader了,因为它没有在您的代码示例中的任何地方定义
  5. 我更改了过滤器以返回离线成员,因为在撰写本文时实际上没有在线成员。

请参考我链接的代码沙箱,以充分了解您在实施我的代码时遇到的任何问题。

注意: navigator.clipboard.writeText()正如您所写,它在代码沙箱中不起作用,但console.log会显示正在写入剪贴板的值是正确的。有关剪贴板的问题应该在他们自己的堆栈溢出帖子中提出。

const Tabledata = ({ guildName }) => {
  const [membersOnline, setMembersOnline] = useState([]);

  useEffect(() => {
    fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
      .then((res) => res.json())
      .then((resp) => {
        const { members } = resp.guild;
        const allCharacters = members.reduce((accum, iter) => {
          accum.push(...iter.characters);
          return accum;
        }, []);

        setMembersOnline(
          allCharacters.filter(({ status }) => status === "offline")
        );
      })
      .catch((err) => console.log(err));
  }, [guildName]);

  return (
    <div className="container">
      <h1>Enemies Online</h1>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th>Name</th>
            <th>Level</th>
            <th>Vocation</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {membersOnline.map((d, i) => (
            <tr
              key={i}
              onClick={(e) => {
                navigator.clipboard.writeText(
                  `exiva ${e.currentTarget.children[0].innerText}`
                );
              }}
            >
              <td>{d.name}</td>
              <td>{d.level}</td>
              <td>{d.vocation}</td>
              <td>{d.status}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Tabledata
于 2021-10-24T06:17:13.023 回答