Мне помог ответ в Unmitigated, если вы ищете в Google, прокрутите вниз
заказ:
[ "567", "645", "852", "645", "852", "852", ]
база данных:
[ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ]
В настоящее время он отлично отображает массив базы данных, но отображает только 3 карты DisplayCard. Мне нужно, чтобы он отображался 6 раз, а также в порядке массива 6 в порядке
{database.map((data, index) => { return <DisplayCard data = {data} key = {index}/> })}
Как сделать так, чтобы он отображался с использованием последовательности массива заказов, не меняя слишком много кода? Поскольку DisplayCard используется в нескольких местах, я бы не хотел ее изменять.
я пытался использовать
{order.map((database.data, index) => { return <DisplayCard data = {database.data} key = {index}/> })}
и ожидал, что он будет использовать последовательность массива заказов и получать данные из соответствующего идентификатора пользователя в массиве базы данных
Но то, что на самом деле получилось, это ошибка, но я не знаю, почему
Редактировать для Unmitigated: Вот минимально воспроизводимый пример, я удалил вызов API и внешнюю ссылку на DisplayCard, и все уместилось в этом фрагменте.
export function Minimal() {
var lookup;
const order= [ "567", "645", "852", "645", "852", "852", ];
const database = [ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ];
function DisplayCard({data}) {
return <div>{data.userId}</div>;
}
return (<>
{database?.length > 0
? lookup = Object.fromEntries(database.map(o => [o.userId, o]))
(
<>
{order.map((userId, index) => {
return <DisplayCard data = {lookup[userId]} key = {index} />
})}
</>
) :
(
<div className = "empty">
<h2>No records found</h2>
</div>
)}
</>)}
Вы можете создать объект, который сопоставляет каждый userId
с объектом в массиве, а затем получать доступ к значениям из этого объекта поиска при использовании order
.
let lookup = Object.fromEntries(database.map(o => [o.userId, o]));
// ...
{order.map((id, index) => <DisplayCard data = {lookup[id]} key = {index}/>)}
Пример:
function DisplayCard({data}) {
return <div>{data.userName}</div>;
}
function App() {
let order = [ "567", "645", "852", "645", "852", "852", ];
let [database, setDatabase] = React.useState([ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ]);
let lookup = Object.fromEntries(database.map(o => [o.userId, o]));
return (
<div>
{order.map((id, index) => <DisplayCard data = {lookup[id]} key = {index}/>)}
<button onClick = {() => setDatabase([{userId: 567, userName: 'changed 567'}, {userId: 645, userName: 'changed 645'}, {userId: 852, userName: 'changed 852'}])}>Change state</button>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
<script crossorigin src = "https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id = "root"></div>
@wynnawinner У вас есть идентификаторы, которых нет в order
?
@wynnawinner Я обновил свой ответ фрагментом, показывающим, что код работает. Вероятно, в вашем коде есть проблема.
Нет, массив базы данных получен из массива заказов через аксиомы, это невозможно.
@wynnawinner Вы можете видеть, что код работает во фрагменте, учитывая информацию, указанную в вопросе. Если это не работает с вашей стороны, предоставьте минимально воспроизводимый пример, демонстрирующий проблему.
Я просто определил все локально и сделал минимальный воспроизводимый пример в редактировании вопроса.
@wynnawinner Проблема в том, что вы определили lookup
не в том месте. Вам нужно объявить его как отдельную переменную. Правильное определение database
как const lookup = Object.fromEntries(database.map(o => [o.userId, o]));
сработает.
Вы имеете в виду просто перемещение строки поиска var после строки базы данных const, верно? Это ошибка Uncaught TypeError: невозможно прочитать свойства неопределенного (чтение «567») Minimal.js
@wynnawinner Нет, я имею в виду полное удаление var lookup
и вместо этого const lookup = Object.fromEntries(database.map(o => [o.userId, o]));
после определения database
. НЕ добавляйте lookup = Object.fromEntries(database.map(o => [o.userId, o]))
внутри JSX. (В настоящее время он стоит после database?.length > 0 ?
, что неверно и должно быть удалено.) Посмотрите, как lookup
определяется и используется в примере фрагмента моего ответа.
Это работает таким образом, но мне нужно, чтобы поиск менялся каждый раз, когда изменяется массив базы данных.
@wynnawinner Как определение lookup
после database
не достигает этого? Просто определите его внутри компонента, а не внутри JSX, и он будет меняться при каждом рендеринге, если database
изменится.
Поскольку база данных является состоянием использования и будет меняться без перезагрузки страницы, которая вызовет код поиска, если я укажу место, которое вы мне сказали. Вот почему я подумал вставить фрагмент jsx, чтобы при обновлении массива базы данных поиск var снова назначался
@wynnawinner Когда вы устанавливаете состояние, компонент перерисовывается, поэтому код внутри запускается снова. Таким образом, правильно определить lookup
внутри компонента.
@wynnawinner Я обновил фрагмент примера в своем ответе, чтобы показать, что он работает с состоянием.
Оооо, мне очень жаль, я думал, что константа поиска не может измениться в этой позиции, и только код в jsx {database?.length...} будет перерисовываться и выполняться повторно из-за изменения состояния базы данных useState?.length, а не всего Минимальный (). Вот и подумал поставить его туда. Спасибо!!!
«У вас есть идентификаторы, которые не существуют по порядку?»
при обновлении заказа требуется некоторое время для возврата запроса на выборку, поэтому в то время, когда он выполняет поиск с использованием массива ids, это приведет к сбою моего реагирующего приложения, потому что поиск будет обновляться быстрее, чем возвращаемый запрос на выборку
{
order.map((id, index) => {
const target = datebase.find(item => item.userId === id)
return target ? <DisplayCard data = {target} key = {index} /> : null
})
}
Я пробовал, но, кажется, всегда возвращает нулевую часть. (Сначала ничего не возвращалось, но я заменил ноль на "тест", и все отображалось "тест")
Может быть, вам следует заменить «===» на «==»?
То, что вам действительно нужно, это не карта, это фильтрация массива базы данных. Метод карты не используется, как вы думаете, см. определение: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Я твердо верю, что это способ без слишком большого изменения кода.
Шаг 1: Отфильтруйте массив базы данных в соответствии с идентификаторами в массиве заказов
Шаг 2: Теперь вы можете использовать отфильтрованный массив базы данных
let resultsFiltered = database.filter(item => order.includes(item.userId))
{resultsFiltered.map((data, index) => { return <DisplayCard data = {data} key = {index}/>})}
DisplayCard.jsx: 10 Uncaught TypeError: Не удается прочитать свойства undefined (чтение «userName») Я все еще пытаюсь понять, что пошло не так, но это ошибка, которую я получил, когда сразу вставил ваш код