Удаление элементов из state по таймеру

96
03 сентября 2021, 14:10

Идея такая: есть локальный state (hook), в нем массив из четырех элементов. На экране есть кнопка добавления нового элемента в этот массив. При загрузке компонента в useEffect вызывается метод, который каждые 5 секунд удаляет первый элемент из стэйта. Если не трогать кнопку, которая добавляет новый элемент в стэйт, то все работает замечательно. Но если начать добавлять элементы, то удаление срабатывает по предыдущему стэйту, только потом отображается стэйт с новым элементом. Подскажите, как это исправить, чтоб все работало стабильно. Я понимаю, что нужно искать в направлении жизненного цикла, происходит конфликт состояний, но решения найти не могу.

const Component = () => {
    const [arr, setArr] = useState(['one', 'two', 'three', 'four']);
    React.useEffect(() => {
        console.log("render");
        setTimeout(deleteElementFromArr, 5000)
    });
    const addNewElementToArr = () => {
        let temp = arr.slice();
        temp.push('newElement');
        setArr(temp);
    };
    const deleteElementFromArr = () => {
        if (arr.length > 0) {
            console.log(arr);
            let temp = arr.slice();
            temp.splice(0, 1);
            setArr(temp)
        }
    };
    return (<div>
        <div>
            <Button onClick={addNewElementToArr}>add</Button>
        </div>
        <div style={{margiTop: '10px'}}>
            {arr.map(a => `${a} `)}
        </div>
    </div>)
};

https://codepen.io/slava4ka/pen/WNNvrPV

Answer 1
const Button = ReactBootstrap.Button
const useState = React.useState
const Component = () => {
    const [arr, setArr] = useState(['one', 'two', 'three', 'four']);
   const [timerId, setTimerId] = useState(null);
    React.useEffect(() => {
       clearTimeout(timerId)
        setTimerId(setTimeout(() => deleteElementFromArr(arr), 1000))
    },[arr]);
    const addNewElementToArr = () => {
        setArr([...arr, 'newElement']);
    };
    const deleteElementFromArr = (arr) => {
        if (arr.length) {
            setArr(arr.slice(0, arr.length - 1))
        }
    };
    return (<div>
        <div>
            <Button onClick={addNewElementToArr}>add</Button>
        </div>
        <div style={{margiTop: '10px'}}>
            {arr.map(a => `${a} `)}
        </div>
    </div>)
};

ReactDOM.render(
    <Component/>,
    document.getElementById('root')
);
READ ALSO
Uncaught ReferenceError: require is not defined. Как избавиться?

Uncaught ReferenceError: require is not defined. Как избавиться?

Собираю проект через GulpТакая проблема: написал код, после "прогона" через babel выдал ошибку: regeneratorRuntime is not defined

164
Как передать дату в ActionCreator

Как передать дату в ActionCreator

У меня есть поле создание поста через input, где после нажатия на enter или кнопки опубликовать пост вызывается функция onAddPost

152
Анимация набора текста на CSS

Анимация набора текста на CSS

Нашел такой вариант создания анимации набора текста, но он почему-то работает только с текстовым абзацемПопробовал сделать тоже самое со span, ничего...

223
Как выполнить setTimeout по очереди в JavaScript?

Как выполнить setTimeout по очереди в JavaScript?

Я только изучаю JS, Подскажите пожалуйста, как выполнить setTimeout по очереди в JavaScript ?

227