更新Autocomplete组件渲染后的选项列表。

huangapple go评论65阅读模式
英文:

How to update the list of options of an Autocomplete component after its rendering

问题

我有这个函数,从URL获取JSON数组,其中包含我想要显示在我的Autocomplete组件中的选项列表。

function ShowMovies() {
    async function GetMovies() {
        movies_list = await fetch(url, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'authorization': token
            },
        }).then(response => movies_list = response.json());
    }
    GetMovies();

    return (
        <Autocomplete
            multiple
            freeSolo
            disablePortal
            id='movies'
            name='movies'
            options={movies_list}
            getOptionLabel={(option) => option.movie_name}
            renderInput={(params) => <TextField {...params} label='New movies:' />}
        />
    );
}
export default ShowMovies;

然而,这会导致无法加载返回的选项,并显示以下警告。根据我的理解,这是因为在将其绑定到组件时,fetch请求仍在进行中。

Warning: Failed prop type: The prop `options` is marked as required in `ForwardRef(Autocomplete)`, but its value is `undefined`.

如何延迟此绑定直到请求完成?

英文:

I have this function which get a JSON array from an URL containing list of options that I want to show as option in my Autocomplete component.

function ShowMovies() {
    async function GetMovies() {
        movies_list = await fetch(url, {
            method: &#39;GET&#39;,
            headers: {
                &#39;Accept&#39;: &#39;application/json&#39;,
                &#39;authorization&#39;: token
            },
        }).then(response =&gt; movies_list = response.json());
    }
    GetMovies();

    return ( &lt;Autocomplete multiple freeSolo disablePortal id = &#39;movies&#39;
        name = &#39;movies&#39;
        options = {
            movies_list
        }
        getOptionLabel = {
            (option) =&gt; option.movie_name
        }
        renderInput = {
            (params) =&gt; &lt; TextField {
                ...params
            }
            label = &#39;New movies:&#39; / &gt;
        }
        /&gt;
    );
    export default ShowMovies;

However, this fails to load returned options and gives me below warning. Which is according to my understanding is because at the time I am binding this to the component the fetch request is still ongoing.

Warning: Failed prop type: The prop `options` is marked as required in `ForwardRef(Autocomplete)`, but its value is `undefined`.

How can I delay this binding until the request is completed?

答案1

得分: 1

在第一次运行时,此函数将返回&lt;AutoComplete [...] /&gt;组件。显然,movies_list未定义,因为它最终会异步填充。该HTTP调用肯定比渲染时间长。

然后,您必须注意两件事:

  1. 函数GetMovies将在每次组件函数的渲染/调用时重新定义,这只是不必要的。
  2. 调用GetMovies()没有进行“等待”,而且更糟糕的是:将该调用放在React函数组件中的这个位置是最糟糕的之一。

为了向您展示更好的方式,让我用JS伪代码重新编写您的构造 - 它将向您显示构图,您可以轻松将其翻译为JavaScript。

function ShowMovies() {
    const [movies, setMovies] = useState([]);

    useEffect(() => {
        fetch('some url', {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'authorization': 'some token'
            },
        }).then(response => response.json())
        .then(json => setMovies(json));
    }, []);

    return <Autocomplete
        multiple
        freeSolo
        disablePortal
        id="movies"
        name="movies"
        options={movies}
        getOptionLabel={(option) => option.movie_name}
        renderInput={(params) => <TextField {...params} label="New movies:" />}
    />;
}

更多细节:

事实上,在组件渲染后再查询其他资源(通过HTTP调用)被称为“副作用”(不仅仅是在React世界中)。它应该与您的渲染逻辑并行发生。useEffect钩子非常适合解决这种问题。请阅读文档!无论如何...以这种方式使用useEffect钩子,使用这些参数,它只在组件首次渲染后运行一次。这是查询数据的最佳时机。当响应到达时,您将其放入状态(useState)对象中,然后强制组件更新(重新渲染),但这次您已经设置了数据。

希望这是一个良好的起点。

阅读React钩子文档

观看一些不错的初学者React教程

英文:

On the first run this function will return the the &lt;AutoComplete [...] /&gt; component. Clearly movies_list is undefined, because it would eventually get populated asynchroniously. That HTTP call will surely take longer than the rendering.

Then you have to be aware of two other things:

  1. The function GetMovies will be defined again on every render / call of your component function which is just unnecessary.
  2. The call GetMovies() is not "awaited", and even worse: it is one of the worst places in a React Function component to place that call.

To show you a better way, let me rewrite your construct with JS - Pseudo code - it will show you the schematics and you can easily translate that into JavaScript.

function ShowMovies() {
    const [movies, setMovies] = useState([]);

    useEffect(() =&gt; {
        fetch(&#39;some url&#39;, {
            method: &#39;GET&#39;,
            headers: {
                &#39;Accept&#39;: &#39;application/json&#39;,
                &#39;authorization&#39;: &#39;some token&#39;
            },
        }).then(response =&gt; response.json())
        .then(json =&gt; setMovies(json));
    }, []);

    return &lt;Autocomplete
        multiple
        freeSolo
        disablePortal
        id=&quot;movies&quot;
        name=&quot;movies&quot;
        options={movies}
        getOptionLabel={(option) =&gt; option.movie_name}
        renderInput={(params) =&gt; &lt;TextField {...params} label=&quot;New 
movies:&quot; / &gt;}
        /&gt;;
}

More details:

The fact, that you query further resources (via that http call) after the component has been rendered is called a "side effect" (not only) in react world. It shall happen in parallel to your rendering logic. The useEffect hook is perfectly suited for this kind of problem. Please read the documentation! Whatever ... used the useEffect hook in this way, with those parameters it just runs once after the component has rendered for the first time. That's the best moment to query for the data. When the response arrives you put it into a state (useState) object, which in turn forces the component to update (render again), but this time with the data at hand you just set.

I hope this is a good starting point.

Read the react hooks docs!

Watch some nice beginner react tutorials!

huangapple
  • 本文由 发表于 2023年5月18日 02:02:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76274992.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定