Затык с пониманием организации течения данных в реакт. Стоит задача - есть массив в стейте, пусть будет
const[arr,setArr]=useState([1,2,3])
. Исходя из данных в этом массиве нужно (к примеру) отрендерить несколько отдельных таймеров. используем мап -
arr.map(el=><TimerComponent name={el}/>)
Получаем условные таймеры с номерами 1,2,3. Вопрос - можно ли добавить еще один таймер к уже существующим, не вызывая перерендера ВСЕХ TimerComponent? Если просто запушить в исходный массив еще одно значение, это вызовет ререндер существующих таймеров, которые попросту запустятся заново. Возможно нужно по другому организовать хранение данных в приложении?
Извиняюсь за отсутствие полного примера исходного кода - слишком запутанный.
UPD: таки придется дополнить с полным кодом)
компонент App
import { useState } from 'react';
import './App.css';
import ControlPanel from './components/ControlPanel/ControlPanel';
import CreateTimer from './components/CreateTimer/CreateTimer';
import Timers from './components/Timer/Timers';
function App() {
//массив с данными таймеров
const [data, setData] = useState([])
// функция с помощью которой обновляю массив с даными из дочернего компонента //CreateTimer
function updateState(newdata) {
setData(pr => [...pr, newdata])
}
return (
<div className="App">
<ControlPanel />
//компонент для добавления таймера
<CreateTimer
updateState={updateState}
/>
//компонент для отрисовки таймеров
<Timers
data={data}
/>
</div>
);
}
export default App;
Компонент CreateTimer
import React, { useState } from "react";
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
export default function CreateTimer(props) {
//значения инпутов
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
//создаю управляемые инпуты
function titleHandler(e) {
setTitle(e.target.value)
}
function descriptionHandler(e) {
setDescription(e.target.value)
}
return (
<Form style={{ width: "100vh", margin: "10px auto" }}>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Название таймера</Form.Label>
<Form.Control type="text"
placeholder="Название"
onChange={(e) => titleHandler(e)}
value={title} />
<Form.Text className="text-muted">
Название не более 4-5 слов.
</Form.Text>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Описание таймера</Form.Label>
<Form.Control type="text"
placeholder="Описание таймера"
onChange={(e) => descriptionHandler(e)}
value={description}
/>
</Form.Group>
<Button variant="primary"
onClick={() => {
//добавляю таймер путем обновления стейта компонента App
let newTimer = {
name: title,
description: description,
time: 0
}
props.updateState(newTimer);
setTitle("")
setDescription("")
}}
>
Создать
</Button>
<hr />
</Form>
)
}
компонент Timers
import React, { useEffect, useState } from "react";
import Table from 'react-bootstrap/Table';
export default function Timers(props) {
//Непосредственно компонент для отрисовки таймера
function Timer(props) {
const [time, setTime] = useState(0)
const [active, setActive] = useState(false)
useEffect(() => {
if (active) {
let myTimer = setInterval(() => {
setTime(time + 1)
}, 1000);
}
})
return (
<tr>
<td>{props.index}</td>
<td>{props.name}</td>
<td>{props.description}</td>
<td>{time}<button
onClick={() => {
setActive(!active)
}}
>start</button></td>
</tr>
)
}
return (
<Table striped bordered hover>
<thead>
<tr>
<th>Номер</th>
<th>Название</th>
<th>Описание</th>
<th>Время</th>
</tr>
</thead>
<tbody>
//здесь отправляю компонент в рендер в таблицу
{props.data.map((el, index) => < Timer
key={el.name}
index={index + 1}
name={el.name}
description={el.description}
time={el.time} />)}
</tbody>
</Table>
)
}
При добавлении нового таймера через CreateTimer идущие таймеры сбрасываются.
Спасибо за любые подсказки.