Изменение компонента внутри другого компонента/реагирующих значков

Я создаю компонент рейтинга, который принимает несколько значков и отображает их с помощью react-icons. Однако мой вопрос касается функции, которую я хотел бы реализовать. В настоящее время я использую значок реакции FaStarhalf, который представляет собой предварительно заполненную половину звезды, которую я переворачиваю, чтобы создать иллюзию, что я создал половину звезды. С ним очень легко работать, и он делает то, что мне нужно, однако я хотел реализовать лучший способ отображения при выборе звезды. К сожалению, у react-icons, похоже, нет возможности заполнить значок полностью. FaRegStarHalf — это еще один компонент из react-icons, который по сути является вырезкой из звезды, однако вы не можете его заполнить.

Итак, мой вопрос к вам. Можно ли внутри моего компонента FaStarHalf при нажатии на него изменить каждый FaStarHalf на его заполненный аналог из react-icons? Могу ли я изменить компонент внутри себя, чтобы он был другим компонентом?

Rater

import React, { useState } from 'react'
import { FaStarHalf } from 'react-icons/fa'

import './styles/Rater.css'

const Rater = ({ iconCount }) => {
    const [rating, setRating] = useState(null)
    const [hover, setHover] = useState(null)
    return (
        <div>
            {[...Array(iconCount), ...Array(iconCount)].map((icon, i) => {
                const value = (i + 1) / 2

                return (
                    <label>
                        <input
                            type='radio'
                            name='rating'
                            value = {value}
                            onClick = {() => {
                                console.info(`value => `, value)
                                return setRating(value)
                            }}
                        />
                        <div className='star-container'>
                            <div>
                                <FaStarHalf
                                    className = {i % 2 ? 'star-left' : 'star'}
                                    color = {value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                                    onMouseEnter = {() => setHover(value)}
                                    onMouseLeave = {() => setHover(null)}
                                />
                            </div>
                        </div>
                    </label>
                )
            })}
        </div>
    )
}

export default Rater
FaHalfStar

FaRegHalfStar

🤔 А знаете ли вы, что...
JavaScript используется для разработки современных одностраничных приложений (SPA), где весь контент загружается асинхронно.


389
2

Ответы:

Решено

Не видя, как выглядят данные, с которыми вы работаете, сложно ответить, но я попробую. Я предполагаю, что вы хотите, когда пользователь щелкает звезду, чтобы установить рейтинг от 1 до 5, вы хотите показать ему его рейтинг в виде заполненных звезд. Если это так, вы можете использовать rating, чтобы определить, показывается ли пользователю текущий рейтинг или рейтинг, который они установили, а затем использовать соответствующий значок по мере необходимости.

Этого можно добиться, установив соответствующую строку в переменную, а затем используя ее вместо имени тега JSX значков. В принципе, если пользователь поставил рейтинг, rating больше не будет null и можно утверждать, что вам нужны заполненные звезды. Используйте эту логику, чтобы присвоить переменную нужной строке. const Star = rating ? 'FaStar' : 'FaHalfStar'

import React, { useState } from 'react'
import { FaStarHalf, FaStar } from 'react-icons/fa'

import './styles/Rater.css'

const Rater = ({ iconCount }) => {
    const [rating, setRating] = useState(null)
    const [hover, setHover] = useState(null)
    // check if user has set a rating by clicking a star and use rating to determine icons
    const Star = rating ? 'FaStar' : 'FaHalfStar'

return (
    <div>
        {[...Array(iconCount), ...Array(iconCount)].map((icon, i) => {
            const value = (i + 1) / 2              
            
            return (
                <label>
                    <input
                        type='radio'
                        name='rating'
                        value = {value}
                        onClick = {() => {
                            console.info(`value => `, value)
                            return setRating(value)
                        }}
                    />
                    <div className='star-container'>
                        <div>
                            // Use 'Star' variable here which is assigned 'FaStar' or 'FaHalfStar' and will display a half star or a full star
                            <Star
                                className = {i % 2 ? 'star-left' : 'star'}
                                color = {value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                                onMouseEnter = {() => setHover(value)}
                                onMouseLeave = {() => setHover(null)}
                            />
                        </div>
                    </div>
                </label>
            )
        })}
    </div>
)
}

export default Rater
FaHalfStar

Я смог понять это, используя аналогичный код того, что использовал @CaseyC, мне нужно было найти соответствующую полузвезду, которая была заполнена, а не полную звезду, которую я пытался использовать

import React, { useState } from 'react'
import { FaRegStarHalf, FaStarHalf } from 'react-icons/fa'

import './styles/Rater.css'

const Rater = ({ iconCount }) => {
    const [rating, setRating] = useState(null)
    const [hover, setHover] = useState(null)
    // check if user has set a rating by clicking a star and use rating to determine icons
    const Star = rating ? FaStarHalf : FaRegStarHalf

    return (
        <div>
            {[...Array(iconCount), ...Array(iconCount)].map((icon, i) => {
                const value = (i + 1) / 2

                return (
                    <label>
                        <input
                            type='radio'
                            name='rating'
                            value = {value}
                            onClick = {() => {
                                console.info(`value => `, value)
                                return setRating(value)
                            }}
                        />
                        <div className='star-container'>
                            <div>
                                <Star
                                    className = {i % 2 ? 'star-left' : 'star'}
                                    color = {value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                                    onMouseEnter = {() => setHover(value)}
                                    onMouseLeave = {() => setHover(null)}
                                />
                            </div>
                        </div>
                    </label>
                )
            })}
        </div>
    )
}

export default Rater