簡體   English   中英

React.js 中的功能組件內部去抖動

[英]Debounce inside functional component in React.js

嘗試在具有隨更改更新的輸入字段的反應組件上創建延遲。

這是代碼:

import React from 'react'; 
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...

const SampleRow = () => {
    let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn: ''});

    const onAddFriend = debounce(() => {
        if(newFriend.name.length === 0){
            return;
        }
        console.log(newFriend.name);
    }, 2000);

    return (
        <TableRow>
            <TableCell component="th" scope="row">
                <Input
                    value={newFriend.name}
                    onChange={(event) => {
                        setNewFriend({...newFriend, name: event.target.value});
                        onAddFriend();
                    }}
                    placeholder={"Add friend"}
                    disableUnderline={true}
                />
            </TableCell>
            <TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
            <TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
            <TableCell align="left" className={classes.externalLinks}/>
        </TableRow>
    )
};

發生的情況是console.log打印出每個更改(在 2s 超時之后),並且不會取消以前的觸發器。

問題是為什么會這樣? 這怎么可能解決?

我在復雜的useDebounce邏輯或類組件中發現了類似的問題。 沒有找到這個問題的參考。

這里的問題是您的去抖動 function 正在每次渲染上重新創建。

解決此問題的一種方法是將其移出功能組件。 另一種方法是將組件更改為 Class 組件並將去抖動的 function 保存為屬性。

 const { useState } = React const { debounce } = _; const onAddFriend = debounce(console.log, 2000); const App = () => { const [newFriend, setNewFriend] = useState({name: '', lastSeen: '', contactIn: ''}); const handleInput = (event) => { setNewFriend({...newFriend, name: event.target.value}); onAddFriend(event.target.value); } return ( <div className="box"> <form className="form"> <div class="field"> <label for="name-1">Update {newFriend.name}</label> <div class="control"> <input type="text" name="name-1" value={newFriend.name} onChange={handleInput} class="input"/> </div> </div> </form> </div> ) } ReactDOM.render(<App />, document.getElementById("root"))
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script> <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script> <div id="root"></div>

Ciao,嘗試取消之前的觸發器:

import React from 'react'; 
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...

const SampleRow = () => {
  let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn: 
''});

const onAddFriend = debounce((abort) => {
    if(abort){
        return;
    }
    console.log(newFriend.name);
}, 2000);

return (
    <TableRow>
        <TableCell component="th" scope="row">
            <Input
                value={newFriend.name}
                onChange={(event) => {
                    setNewFriend({...newFriend, name: event.target.value});
                    let abort = false;
                    if(event.target.value.length === 0){
                      abort = true;
                    }
                    onAddFriend(abort);
                }}
                placeholder={"Add friend"}
                disableUnderline={true}
            />
        </TableCell>
        <TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
        <TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
        <TableCell align="left" className={classes.externalLinks}/>
    </TableRow>
)
  };

嘗試這個。 它將始終檢查隊列中現有的去抖動,並取消它找到任何。 參考: 如何在調用之后和執行之前取消去抖動的 function?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM