javascript 如何基于API调用呈现一个示例

jxct1oxe  于 2023-11-15  发布在  Java
关注(0)|答案(1)|浏览(85)

我想知道如何在Outlook外接程序中使用API调用填充后呈现一个插件。它不会显示在屏幕上。
基本示例:

const App () => {
    let contactDropdown = <></>;

    (async () => {
        await Office.onReady();

        const contacts = await getContacts();
        contactDropdown = buildDropdown(contacts);
    })();

    const buildDropdown = (contacts) => {
        //e.g.:
        // contacts = [
        //     { value: 1, text: "Tim" },
        //     { value: 2, text: "Fred" }
        // ];

        return (
            <div>
                <label>Choose a Contact</label>
                <select>
                    {contacts.map((option) => (
                        <option key={option.value} value={option.value}>
                          {option.text}
                        </option>
                      ))}
                </select>
            </div>
          );
    };

    return (
        <div>
          {contactDropdown}
        </div>
    );
}

字符串
我需要先使用useEffect和state来加载数据吗?我试过了,但它不起作用。

const [contacts, setContacts] = useState([]);
  useEffect(() => {
    setContacts(getContacts());
  }, []);

  const getContacts = async () => {
    //api call here
  };

w51jfk4q

w51jfk4q1#

首先,您不必等待获取数据来定义EJB组件。
其次,在尝试使用state时,您将promise存储在state中,而不是实际结果。
概念验证:

const ContactsDropdown = () => {
  const [contacts, setContacts] = useState([])
  const [loading, setLoading] = useState(false)
  useEffect(() => {
    setLoading(true)
    getContacts()
      .catch((err) => (console.error(err), []))
      .then((r) => {
        setLoading(false)
        setContacts(r) // or r.data!? (depends on server response)
      })
  }, [])
  return (
    <div>
      {loading && <div>loading contacts...</div>}
      {!loading && !contacts.length && <div>no contacts loaded!</div>}
      {!loading && contacts.length && (
        <>
          <label>Choose a Contact</label>
          <select>
            {contacts.map(({ value, text }) => (
              <option key={value} value={value}>
                {text}
              </option>
            ))}
          </select>
        </>
      )}
    </div>
  )
}

字符串
为了简洁起见,上面的组件执行数据的获取,但这可能并不理想。
更有意义的做法可能是将该状态提升到父组件中,并在获取联系人后将其作为一个 prop 传递给代理。
下面是它可能的样子(仍然是最基本的,但演示了原理):

const { useState, useEffect } = React
const ContactsDropdown = ({ contacts, ...props }) => (
  <select {...props}>
    <option>-- Select a contact --</option>
    {contacts.map(({ id, name }) => (
      <option key={id} value={id}>
        {name}
      </option>
    ))}
  </select>
)
const App = () => {
  const [contacts, setContacts] = useState([])
  const [selected, setSelected] = useState()
  const [loading, setLoading] = useState(false)
  useEffect(() => {
    setLoading(true)
    // delay by a second, to demo loading..
    setTimeout(() => {
      fetch('https://jsonplaceholder.typicode.com/users')
        .then((response) => response.json())
        .then(setContacts)
        .then(setLoading)
    }, 1e3)
  }, [])
  const cdProps = {
    contacts,
    value: (selected && selected.id) || '',
    onChange: ({ target: { value } }) =>
      setSelected(contacts.find(({ id }) => id === +value))
  }
  return (
    <React.Fragment>
      {loading && <div>contacts loading...</div>}
      {!loading && !contacts.length && <div>no contacts!</div>}
      {!loading && contacts.length && <ContactsDropdown {...cdProps} />}
      <pre>{JSON.stringify({ selected }, null, 2)}</pre>
    </React.Fragment>
  )
}
ReactDOM.createRoot(root).render(<App />)
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>

的数据

相关问题