我想知道在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
  };

推荐答案

首先,您不必等待获取数据来定义DropDown组件.

其次,在您try 使用状态时,您存储的是promise 内部状态,而不是实际结果.

概念验证:

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>
  )
}

为简单起见,上面的组件执行数据获取,但这可能并不理想.

将该状态提升到父组件中,并将联系人作为props 向下传递到下拉列表中可能更有意义,一旦它们被获取.

下面是它可能的样子(仍然是基本的,但演示了原理):

const { useState, useEffect, Fragment } = 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],
    [selected, setSelected],
    [loading, setLoading]
  ] = [[], null, false].map(useState)
  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(false))
    }, 1e3)
  }, [])
  const cdProps = {
    contacts,
    value: (selected && selected.id) || '',
    onChange: ({ target: { value } }) =>
      setSelected(contacts.find(({ id }) => id === +value) || null)
  }
  return (
    <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>
    </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>

Javascript相关问答推荐

如何在Node.js中减go 两个日期和时间?

在JavaScript中使用setProperty方法试图修改css元素值时,我遇到错误

Webpack将懒惰加载的模块放入主块中

同步功能在中间停止

如何通过继承contentitable属性的元素捕捉keydown事件?

用户单击仅在JavaScript中传递一次以及其他行为

模块与独立组件

如何禁用附加图标点击的v—自动完成事件

有没有可能使滑动img动画以更快的速度连续?

更改JSON中使用AJAX返回的图像的路径

如何从HTML对话框中检索单选项组的值?

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

提交链接到AJAX数据结果的表单

在数组中查找重叠对象并仅返回那些重叠对象

Use Location位置成员在HashRouter内为空

当用户点击保存按钮时,如何实现任务的更改?

将对象推送到数组会导致复制

如何根据查询结果重新排列日期

使用Reaction窗体挂钩注册日历组件

如何通过Axios在GraphQL查询中发送数组