#reactjs #typescript #mongodb #list #ids
Вопрос:
Я разрабатываю список элементов, используя React, Express (axios) и MongoDB.
Элементы массива списка извлекаются из MongoDB, отображаются в компоненте, и пользователь может добавлять новые элементы (и сохранять их в MongoDB).
Проблема в том, что Warning: Each child in a list should have a unique "key" prop"
отображается, потому что новый элемент добавляется в список с помощью id: Math.random()
атрибута (хотя эти идентификаторы не передаются в БД).
App.tsx (ЗДЕСЬ список элементов извлекается с идентификаторами, сгенерированными MongoDB)
export default function App() {
const [ExpenseAndAmountList, setExpenseAndAmountList] = useState<
Array<{
id: number,
expenseTitle: string,
expenseAmount: string,
}>
>([]);
useEffect(() => {
const expensesListResp = async () => {
await axios.get('http://localhost:4000/app/expenseslist')
.then(
response => setExpenseAndAmountList(response.data amp;amp; response.data.length > 0 ? response.data : []));
}
expensesListResp();
}, []);
return (
<div className="App">
<ExpenseAmountInputContainer
expenseAndAmountList={ExpenseAndAmountList}
setExpenseAndAmountList={setExpenseAndAmountList}
setTotalExpensesAmount={setTotalExpensesAmount}
totalExpenses={TotalExpensesAmount}
/>
<DynamicList
expenseAndAmountList={ExpenseAndAmountList}
currencySymbol={Currency}
setExpenseAndAmountList={setExpenseAndAmountList}
/>
</div>
);
}
ExpenseAmountInputContainer.tsx (ЗДЕСЬ элементы размещаются в списке MongoDB без какого-либо идентификатора)
interface Props {
expenseAndAmountList: Array<ExpenseAndAmountObject>;
setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
}
const ExpenseAmountInputContainer: React.FC<Props> = (
{
expenseAndAmountList,
setExpenseAndAmountList,
}: Props
) => {
const [Expense, setExpense] = useState<string>('');
const [Amount, setAmount] = useState<string>('');
const AddItemToList = () => {
if (Expense !== '' amp;amp; Amount !== '' amp;amp; Number(Amount) > 0) {
axios.post('http://localhost:4000/app/expenseslist',
{
expenseTitle: Expense,
expenseAmount: Amount
});
setExpense("");
setAmount("");
const expensesListResp = async () => {
await axios.get('http://localhost:4000/app/expenseslist')
.then(
response => setExpenseAndAmountList(response.data amp;amp; response.data.length > 0 ? response.data : []));
}
expensesListResp();
}
return (
<div>
<InputItem
onChange={setExpense}
onBlur={setExpense}
title="Expense"
type="text"
placeholder="Item title"
value={Expense}
/>
<InputItem
onChange={setAmount}
onBlur={setAmount}
title="Amount"
type="number"
placeholder="Expense cost"
value={Amount}
/>
<AddButton
onClick={AddItemToList}
content="Add expense"
/>
</div>
);
};
export default ExpenseAmountInputContainer;
ExpenseAndAmountObject.tsx (интерфейс, используемый в ExpenseAmountInputContainer.tsx)
export interface ExpenseAndAmountObject {
id: number,
expenseTitle: string,
expenseAmount: string,
}
DynamicList.tsx
import { ExpenseAndAmountObject } from '../ExpenseAndAmountObject';
interface ListItemsArray {
expenseAndAmountList: Array<ExpenseAndAmountObject>;
currencySymbol: string;
setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
}
const DynamicList: React.FC<ListItemsArray> = (
{
expenseAndAmountList,
currencySymbol,
setExpenseAndAmountList
}: ListItemsArray) => {
return (
<>
<List>
{expenseAndAmountList.map(item => (
<ExpensesListItem
expenseTitle={item.expenseTitle}
expenseAmount={item.expenseAmount}
currencySymbol={currencySymbol}
item={item}
items={expenseAndAmountList}
setExpenseAndAmountList={setExpenseAndAmountList}
/>
))}
</List>
</>
);
}
export default DynamicList;
Как можно было бы решить эту проблему?
Комментарии:
1. Где вы задаете свойства идентификатора элемента? Вы устанавливаете их в бэкэнде?
Math.random
на самом деле это не очень хороший вариант использования для создания уникальных идентификаторов.2. Мой комментарий вводил в заблуждение, я им не пользовался
Math.random
. ЗА свой счет элементы Mountinputcontainer.tsx разносятся в MongoDB без каких-либо идентификаторов (поскольку они генерируются в MongoDB)3. Как бы то ни было, все еще неясно, куда вы добавляете какие-либо
id
свойства при добавлении новых элементов в список. Где генерируютсяid
s? Где возникает ошибка? Похоже, вы генерируете их в своем бэкэнде. Если они не уникальны, то у вас возникнет эта проблема с интерфейсом. Можем ли мы увидеть соответствующий внутренний код?4. В DynamicList.tsx вы устанавливаете ключевые параметры для компонентов, созданных с использованием
map()
?5. Я нигде не устанавливал ключевую опору, и я просто добавил атрибут
key={item.id}
в<List>
. Я пытаюсь этого добиться item.id будет_id
сгенерирован MongoDB (может быть, это неправильный подход..?)
Ответ №1:
Вам нужно передать реквизит key
при визуализации списков.
import { ExpenseAndAmountObject } from '../ExpenseAndAmountObject';
interface ListItemsArray {
expenseAndAmountList: Array<ExpenseAndAmountObject>;
currencySymbol: string;
setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
}
const DynamicList: React.FC<ListItemsArray> = (
{
expenseAndAmountList,
currencySymbol,
setExpenseAndAmountList
}: ListItemsArray) => {
return (
<>
<List>
{expenseAndAmountList.map(item => (
<ExpensesListItem
key={} // <----- SOME UNIQUE ID HERE!!!!!!!!
expenseTitle={item.expenseTitle}
expenseAmount={item.expenseAmount}
currencySymbol={currencySymbol}
item={item}
items={expenseAndAmountList}
setExpenseAndAmountList={setExpenseAndAmountList}
/>
))}
</List>
</>
);
}
export default DynamicList;
Пожалуйста, ознакомьтесь с документацией, объясняющей такое поведение https://reactjs.org/docs/lists-and-keys.html#keys
Комментарии:
1. Я добавил атрибут
key={item.id}
<List>
в соответствии с вашим примером. item.id предполагается_id
, что он генерируется MongoDB (я проверил, что в динамическом списке компонентов массив элементов из MongoDB доступен, т. Е. равен[{_id: "60c970297ba73b083ec13dbc", expenseTitle: “first_title, expenseAmount: "1", __v: 0},{_id: "60c9782dae534110361f359a", expenseTitle: “second”title, expenseAmount: “2”, __v: 0}]
). Однако, когда я проверяю значения реквизитов элементов в ExpensesListItem, значениеkey={item.id} equals to undefined
. Может быть, вы знаете, почему? Заранее спасибо!