Как отобразить массив в react js, который содержит объект?

#javascript #reactjs #mapping

#javascript #reactjs #отображение

Вопрос:

index.js

 const UserSearch = ({ user }) => {

    const [resultsToShow, setResultsToShow] = useState([])

    const maxDistance = useFilter('matchaMaxDistance', 100, 'number')
    const minAge = useFilter('matchaMinAge', 20, 'number')
    const maxAge = useFilter('matchaMaxAge', 120, 'number')
    const minFame = useFilter('matchaMinFame', 100, 'number')
    const requiredTag = useFilter('matchaRequiredTag', '', 'text')

    const sortFormProps = ({ user, resultsToShow, setResultsToShow })
    const filterFormProps = ({ user, requiredTag, maxDistance, minFame, minAge, maxAge })

    const requiredTagFound = tags => tags amp;amp; requiredTag.value
        ? tags.split('#').includes(requiredTag.value)
        : true

    const filterResults = () => resultsToShow
        ? resultsToShow
            .filter(r => r.distance <= maxDistance.value amp;amp;
                r.age.years >= minAge.value amp;amp; r.age.years <= maxAge.value
                amp;amp; r.fame >= minFame.value amp;amp; requiredTagFound(r.tags))
        : []
var unblockedUser = [];

    useEffect(() => {
        var coords = JSON.parse(window.localStorage.getItem('loggedMatchaUser'));
        var from_user_id = coords.user_id;
        
        var res = filterResults();
        console.log(typeof res)
        res.map((r) => {
            var to_user_id = r.user_id;
            blockService.blockedUser({from_user_id, to_user_id})
            .then(res => {
                //If this row exist in the table it return 1 otherwise 0
                if (res.value === 0)
                {
                    //console.log(r);
                    unblockedUser.push(r)
                }
            })
            .catch(e => {
                console.log(("Error: couldn't get block info"))
            })
        })
    }, [filterFormProps])
    //console.log(unblockedUser)

    return <>

        <ListOfUsers users={unblockedUser} />

    </>
}

export default UserSearch
 

ListOfUsers.js

 const ListOfUsers = ({ users }) => {
    console.log(users);

    return  (
        users amp;amp; users.length > 0
            ? <ListGroup className="text-left" variant="flush">
                {users.map(u => <Link to={`/users/${u.user_id}`} key={u.user_id}>
                        <ListGroup.Item>
                            <div style={{display: "inline-block", width: "60%"}}>{u.username}, {u.age.years}</div>
                            <div style={{display: "inline-block", width: "40%", textAlign: "right"}}>{parseInt(u.distance)} km<br />
                            <FontAwesomeIcon icon={faAward} /> {u.fame}</div>
                        </ListGroup.Item>
                </Link>)}
            </ListGroup>
            : <div className="text-info">Could not find any matching users<br />please try different filters</div>
    )
}
 

Я работаю с поиском пользователей. Моя конечная цель — отобразить список пользователей, кроме заблокированных пользователей, в качестве результата поиска зарегистрированного пользователя. Что я пытаюсь здесь сделать, так это то, что я отправляю unblockedUser в качестве реквизита компоненту ListOfUsers. В компоненте ListOfUsers, если я консольный пользовательский реквизит, он выглядит следующим образом
введите описание изображения здесь

Мой вопрос в том, почему моя функция map не работает здесь, в компоненте ListOfUsers. Как я могу заставить его работать? Кроме того, если я утешаю длину пользователей, она возвращает undefined.

Заранее спасибо

Ответ №1:

Я думаю, нужно создать геттер, сеттер, используя unblockedUser в качестве useState .

 const [unblockedUser, setUnblockedUser] = useState([]); // try it this

    useEffect(() => {
        const coords = JSON.parse(window.localStorage.getItem('loggedMatchaUser'));
        const from_user_id = coords.user_id;
        
        const res = filterResults(); //how does work filterResults() funtinon?
        console.log(typeof res)

        res.map((r) => {
            const to_user_id = r.user_id;
            blockService.blockedUser({from_user_id, to_user_id})
            .then(res => {
                //If this row exist in the table it return 1 otherwise 0
                if (res.value === 0)
                {
                    //console.log(r);
                    setUnblockedUser((prevState) => [...prevState, r]) //here
                }
            })
            .catch(e => {
                console.log(("Error: couldn't get block info"))
            })
        })
    }, [filterFormProps]) // => [] to change
    //console.log(unblockedUser)

    return <>

        <ListOfUsers users={unblockedUser} />

    </>

 

Возможно, вы не полностью функциональны, потому что функция другой функции не объяснена, но попробуйте.

Комментарии:

1. Здравствуйте, спасибо за ваш комментарий. А вот функция filterResults(): « const filterResults = () => resultsToShow ? resultsToShow .filter(r => r.distance <= maxDistance.value amp;amp; r.age.years >= minAge.value amp;amp; r.age.years <= maxAge.value amp;amp; r.fame >= minFame.value amp;amp; requiredTagFound(r.tags)) : [] «

2. Я обновил свой вопрос другими кодами. Пожалуйста, проверьте. Ваш приведенный выше ответ не будет работать. Ваш код отображает компонент бесконечное количество раз (он не останавливается). Это означает, что он постоянно попадает в базу данных и извлекает данные из таблицы. Это не останавливается. Мне пришлось остановить серверный сервер, который является узлом js

3. @Mahmudul Hasan Пожалуйста, скажите мне resultsToShow , какое значение вы хотите обновить. и ‘filterResults’ Обновление события resultsToShow setResultsToShow отсутствует в вашем коде. Причина, по которой рендеринги продолжают происходить, заключается в том, что нам нужно удалить [filterFormProps] useEffect их и посмотреть, работает ли это. [filterFormProps] => [ ]

Ответ №2:

Проблема в том, что вы определяете unblockedUser вне своего useEffect хука, а затем unblockedUser асинхронно обновляете его внутри useEffect . So unblockedUser не получает его содержимое до завершения рендеринга (когда уже слишком поздно), а при следующем рендеринге unblockedUser переопределяется как пустой список.

Чтобы исправить это, я бы сохранил unblockedUser его как переменную состояния, затем вы можете обновить его, как вам нравится, и изменения будут отображаться соответствующим образом.

Например (с минимальными изменениями в существующем коде):

 const [unblockedUser, setUnblockedUser] = React.useState([]); // changed

useEffect(() => {
    var coords = JSON.parse(window.localStorage.getItem('loggedMatchaUser'));
    var from_user_id = coords.user_id;
    
    var res = filterResults();
    console.log(typeof res)
    setUnblockedUser([]); // clear before rerunning
    res.map((r) => {
        var to_user_id = r.user_id;
        blockService.blockedUser({from_user_id, to_user_id})
        .then(res => {
            //If this row exist in the table it return 1 otherwise 0
            if (res.value === 0)
            {
                //console.log(r);
                setUnblockedUser(prev => [...prev, r]); // changed
            }
        })
        .catch(e => {
            console.log(("Error: couldn't get block info"))
        })
    })
}, [filterFormProps])
//console.log(unblockedUser)

return <ListOfUsers users={unblockedUser} />
 

В приведенном выше примере я внес как можно меньше изменений в ваш код, чтобы упростить отслеживание изменений. Вы можете обнаружить, что дополнительные модификации улучшат этот код. Например, вы можете сначала проверить все записи пользователей, получить один массив разблокированных пользователей, а затем вызвать setUnblockedUser один раз вместо нескольких раз. Но решать вам.

Комментарии:

1. Привет @Henry, спасибо за комментарий. Ваш код выдает это предупреждение Предупреждение: обнаружено два дочерних элемента с одним и тем же ключом, 10 . Ключи должны быть уникальными, чтобы компоненты сохраняли свою идентичность при обновлениях. Неуникальные ключи могут Этот код отображает компонент бесконечное время (он не останавливается). Это означает, что он постоянно попадает в базу данных и извлекает данные из таблицы. Это не останавливается. Мне пришлось остановить внутренний сервер, который является node js. Знаете, почему это происходит?

2. Я обновил свой вопрос другими частями своего кода. Пожалуйста, проверьте 🙂

3. @MahmudulHasan Ах да, не хватало вызова для очистки unblockedUser перед повторным заполнением. Сделано обновление