Как передать состояние useReducer дочернему компоненту?

#reactjs #react-redux

#reactjs #react-redux

Вопрос:

У меня есть простое приложение обратной связи, которое содержит несколько компонентов. app.js — родительский компонент

data.js — это содержит фиктивные данные, которые имеют имя и список просмотра

компонент

  • пользователь — этот компонент будет отображать имя и эскиз
  • отзыв — здесь будет отображен список отзывов о пользователе, а также кнопка с надписью оставить отзыв.
    • модальный — после того, как пользователь нажмет кнопку оставить отзыв, появится этот модальный элемент со списком элементов, который обновит список отзывов

Я использовал useReducer для обновления состояния. Но проблема в том, что review.js не показывайте обновленное состояние. может быть, потому, что useReducer находится на modal.js . Что мне следует сделать, чтобы я также мог обновлять данные, отображаемые на review.js

App.js

 function App() {
  return (
    <div className="main-container">
      <DisplayUser />
      <div className="mainContent-container">
        <DisplayReview />
      </div>
    </div>
  );
}
 

User.js

 import { data } from '../../src/data';

const CommentHandler = () => {
    const [user] = React.useState(data);
    return (
        <>
            {user.map((person) => {
                const { id, name, thumbnail } = person;

                return (
                    <div key={id} className='user-container'>
                        <h2 className="user-name">{name}</h2>
                        <img src={thumbnail} alt={name} title={name} className='user-icon' />
                    </div>
                );
            })}
        </>
    );
};
 

Review.js

 import DisplayModal from './Modal'
import Modal from 'react-modal';
import { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { data } from '../../src/data';

const ReviewHandler = () => {
    const [user] = useState(data);
    const [showModal, setShowModal] = useState(false);

    return (
        <>
            {user.map((person) => {
                const { listOfReview } = person;
                return (
                    <div key={person.id} className='review-container active'>
                        <div className="content-container">
                            {listOfReview.map((sub) => {
                                const { reviewId, rating, name, occupation, review } = sub;
                                return (
                                    <div key={reviewId} className="content-container">
                                        <div className='reviewer-rating'>
                                            <div className="static-review">
                                                {[...Array(5)].map((star, index) => {
                                                    return <FontAwesomeIcon key={index} className="star" icon="star" />
                                                })}
                                            </div>
                                            <div className="dynamic-review">
                                                {[...Array(rating)].map((star, index) => {
                                                    return <FontAwesomeIcon key={index} className="star" icon="star" />
                                                })}
                                            </div>
                                        </div>
                                        <div className="user-description">
                                            <h3>{occupation}</h3>
                                            <h4>{name}</h4>
                                            <p>{review}</p>
                                        </div>
                                    </div>
                                )
                            })}
                            <button className="submit" onClick={() => setShowModal(true)}>LEAVE AREVIEW</button>
                        </div>
                    </div>
                );
            })}
            <Modal isOpen={showModal} ariaHideApp={false}>
                <DisplayModal onClick={(value) => setShowModal(value)} />
            </Modal>
        </>
    );
};
 

Modal.js

 import { useState, useReducer } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { data } from '../../src/data';
import { reducer } from './reducer';

const ModalHandler = props => {
    const [rating, setRating] = useState(null);
    const [name, setName] = useState('');
    const [occupation, setOccupation] = useState('');
    const [reviews, setReviews] = useState('');
    const [state, dispatch] = useReducer(reducer, data);
    const [hoverRating, setHoverRating] = useState(null);

    const handelSubmit = (e) => {
        e.preventDefault();
        if (name amp;amp; occupation amp;amp; reviews) {
            const newReview = { reviewId: new Date().getTime(), name, occupation, rating, reviews };
            dispatch({
                type: 'ADD_REVIEW_ITEM',
                payload: newReview
            });
        }
    }

    return (
        <div className="modal-container">
            <div className="modal-backdrop">
                <form className="modal-inner" onSubmit={handelSubmit}>
                    <h2>Feel feel to send us your review!</h2>
                    <div className='revieweRating-container'>
                        <h3>How was your experience?</h3><p onClick={() => props.onClick(false)}>X</p>
                        <div className="dynamic-review">
                            {[...Array(5)].map((star, i) => {
                                const ratingValue = i   1;
                                return (
                                    <label>
                                        <input type="radio"
                                            name="review-star"
                                            value={ratingValue}
                                            onMouseEnter={() => setHoverRating(ratingValue)}
                                            onMouseLeave={() => setHoverRating(ratingValue)}
                                            onClick={() => setRating(ratingValue)}>
                                        </input>
                                        <FontAwesomeIcon
                                            icon="star"
                                            onMouseEnter={() => setHoverRating(ratingValue)}
                                            onMouseLeave={() => setHoverRating(ratingValue)}
                                            color={ratingValue <= (hoverRating || rating) ? "#FAD020" : "#BCC5D3"}
                                            className="review-star" />
                                    </label>
                                )
                            })}
                        </div>
                    </div>
                    <input
                        type="text"
                        name="name"
                        className="name"
                        placeholder="Name"
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                    />
                    <input
                        type="text"
                        name="occupation"
                        className="alioccupationas"
                        placeholder="Aloccupationias"
                        value={occupation}
                        onChange={(e) => setOccupation(e.target.value)}
                    />
                    <textarea
                        name="review"
                        cols="30"
                        rows="6"
                        className="review"
                        placeholder="Enter your review here!"
                        value={reviews}
                        onChange={(e) => setReviews(e.target.value)}>
                    </textarea>
                    <button type="submit" className="submit">SEND A REVIEW</button>
                </form>
                <div>
                    {state.map((data) => (
                        <div key={data.id}>
                            {data.listOfReview.map((review) => (
                                <div key={review.reviewId}>
                                    <h3>{review.name}</h3>
                                    <p>{review.occupation}</p>
                                </div>
                            ))}
                        </div>
                    ))}
                </div>
            </div>
        </div >
    );
}
    
 

reducer.js

 export const reducer = (state, action) => {
    switch (action.type) {
        case "ADD_REVIEW_ITEM":
            console.log(state);
            return state.map((data) => {
                if (data) {
                    const newReview = [...data.listOfReview, action.payload];

                    return {
                        ...data,
                        listOfReview: newReview
                    };
                }
                return data;
            });
        default:
            return state;
    }
};
    
 

data.js

 export const data = [
    {
        id: 1607089645363,
        name: 'Andress Bonifacio',
        noOfReview: 1,
        listOfReview: [
            {
                reviewId: 1607089645361,
                name: 'Juan Dela Cruz',
                occupation: 'Father of Phil. Revolution',
                rating: 5,
                review: 'Numquam labore or dolorem enim but accusantium and autem ratione.',
            }
        ]
    }
];
 

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

1. Трудно быть в состоянии помочь, не видя какого-либо кода, не могли бы вы опубликовать компоненты, которые используют редуктор, а также определение самого редуктора и любой другой код, который, по вашему мнению, может иметь отношение к делу?

2. Конечно, я уже обновил приведенный выше код. пользователь находится на modal.js

Ответ №1:

Если вы хотите получить обновление data для всех компонентов, убедитесь, что эта строка кода const [state, dispatch] = useReducer(reducer, data); доступна во всех component , которые их используют, например, в:-

в User.js

 import { data } from '../../src/data';
import { reducer } from './reducer';

const CommentHandler = () => {
    // not this
    const [user] = React.useState(data);
    // instead this
    const [state, dispatch] = useReducer(reducer, data);
    
    return (
        <>
            {state.map((person) => {
                const { id, name, thumbnail } = person;

                return (
                    <div key={id} className='user-container'>
                        <h2 className="user-name">{name}</h2>
                        <img src={thumbnail} alt={name} title={name} className='user-icon' />
                    </div>
                );
            })}
        </>
    );
};
 

в Review.js

 import { useState, useReducer } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { data } from '../../src/data';
import { reducer } from './reducer';

const ReviewHandler = () => {
    // not this
    // const [user] = useState(data);
    // instead this
    const [state, dispatch] = useReducer(reducer, data);
    const [showModal, setShowModal] = useState(false);

    return (
        <>
            {state.map((person) => {
                const { listOfReview } = person;
                return (
                    <div key={person.id} className='review-container active'>
                        <div className="content-container">
                            {listOfReview.map((sub) => {
                                const { reviewId, rating, name, occupation, review } = sub;
                                return (
                                    <div key={reviewId} className="content-container">
                                        <div className='reviewer-rating'>
                                            <div className="static-review">
                                                {[...Array(5)].map((star, index) => {
                                                    return <FontAwesomeIcon key={index} className="star" icon="star" />
                                                })}
                                            </div>
                                            <div className="dynamic-review">
                                                {[...Array(rating)].map((star, index) => {
                                                    return <FontAwesomeIcon key={index} className="star" icon="star" />
                                                })}
                                            </div>
                                        </div>
                                        <div className="user-description">
                                            <h3>{occupation}</h3>
                                            <h4>{name}</h4>
                                            <p>{review}</p>
                                        </div>
                                    </div>
                                )
                            })}
                            <button className="submit" onClick={() => setShowModal(true)}>LEAVE AREVIEW</button>
                        </div>
                    </div>
                );
            })}
            <Modal isOpen={showModal} ariaHideApp={false}>
                <DisplayModal onClick={(value) => setShowModal(value)} />
            </Modal>
        </>
    );
};
 

Я бы посоветовал вам попробовать и использовать context api вместо того, чтобы просто полагаться на useReducer .

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

1. Вы можете обратиться к этой изолированной среде, если вам не терпится изменить свое приложение для использования Context API