Как передать данные из дочернего компонента в родительский, а затем в родственный брат этого родителя? - PullRequest
0 голосов
/ 30 января 2020

Не уверен, что это глупый вопрос, но я хочу передать данные от дочернего компонента к родителю, и оттуда данные должны быть переданы родному брату его родителя. Не уверен, что это технически возможно, но я хочу использовать переключатель, чтобы проверить, установлено ли для image.enableReply значение true или false.

// child
const CommentSection = ({ index, comments }) => {
    const dispatch = useDispatch();

    const checkLikeComment = (generalIndex, nestedCommentIndex) => {
        console.log(generalIndex, nestedCommentIndex);
        dispatch(likeComment(generalIndex, nestedCommentIndex));
    }

    const enableReplyComment = (generalIndex, nestedCommentIndex) => {
        console.log(generalIndex, nestedCommentIndex, enableReply);
        dispatch(enableReply(generalIndex, nestedCommentIndex))
    }

    const currentComments = comments.map((image, i) => {
        return (
            <div key={i}>
                <div>
                    <div onClick={() => enableReplyComment(index, i, false)}>{image.enableReply ? 'x': 'Reply'}</div>
                </div>

            </div>
        )
    })

    return (
        <div>
            {currentComments}
        </div>
    )
}

const mapStateToProps = state => ({
    images: state.imageData
})

export default connect(mapStateToProps, null)(CommentSection);

// parent
const Images = ({ images }) => {
 const getImages = images.imageData.map((image, index) => {
        return (
            <div key={index} >
                // data should be passed from child to CommentSection
                <CommentSection id={image.id} comments={image.comments} index={index} /> 
                // And then pass it to its sibling
                {image.enableComment ? <PostComment id={image.id}/> : <div></div>} 
        )
    
    });
 }

Ответы [ 4 ]

0 голосов
/ 30 января 2020

С вам на самом деле не нужно делить ваши данные назад и вперед между компонентами.

Если вы хотите, чтобы определенные данные были доступны для нескольких разбросанных компонентов, вы можете отправить некоторые действие (скажем, LIKE увеличение like count в глобальном состоянии) из компонента source (с помощью useDispatch()) и извлечение необходимых данных (like count) из хранилища, где бы они ни находились вам это нужно (используя useSelector()):

//dependencies
const { useState } = React,
      { render } = ReactDOM,
      { createStore } = Redux,
      { useSelector, useDispatch, Provider } = ReactRedux
      
//mock source images pool
const images = {
  tiger: 'https://i.dailymail.co.uk/1s/2019/10/29/14/20320992-7625529-Cara_a_five_year_old_125lb_Bengal_tiger_has_been_fitted_with_a_g-a-8_1572358357911.jpg',
  tan: 'https://www.bioexpedition.com/wp-content/uploads/2013/05/Orangutan_close_up.jpg',
  giraffe: 'https://img.thedailybeast.com/image/upload/c_crop,d_placeholder_euli9k,h_1440,w_2561,x_0,y_0/dpr_1.5/c_limit,w_1044/fl_lossy,q_auto/v1494008886/articles/2017/04/03/the-internet-s-most-famous-pregnant-giraffe-still-hasn-t-given-birth/170403-jones-pregnant-giraffe-tease_alsbhr'
}
      
//default state, action, reducer, store
const defaultState = {likes:{}},
      LIKE = 'LIKE',
      appReducer = (state=defaultState, action) => {
        switch(action.type) {
          case LIKE: {
            const {payload: imgKey} = action,
                  {likes} = state
            return {...state, likes:{...likes, [imgKey]: (likes[imgKey]||0)+1}}
          }
          default: return state
        }
      },
      store = createStore(appReducer)
      
//Image component
const Image = ({imgSrc, imgKey}) => {
  const dispatch = useDispatch(),
        onLikeHit = imageKey => dispatch({type:LIKE, payload: imageKey})
  return (
    <div>
      <img src={imgSrc} imageKey={imgKey} />
      <div className="likebtn" onClick={() => onLikeHit(imgKey)}/>
    </div>
  )
}

//Image gallery
const ImageGallery = ({images}) => (
  <div>
    {Object.entries(images).map(([imgKey,imgSrc],key) => <Image {...{imgKey, imgSrc, key}} />)}
  </div>
)

//Likes summary:
const Likes = () => {
  const likes = useSelector(({likes}) => likes)
  return (
    <div>
      {Object.entries(likes).map(([photo,count]) => <div>{photo}:{count}</div>)}
    </div>
  )
}

//entire App
render (
  <Provider {...{store}}>
    <ImageGallery {...{images}} />
    <Likes />
  </Provider>,
  document.getElementById('root')
)

      
img {
  max-width: 150px;
}

.likebtn {
  width:30px;
  height:30px;
  background-image: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTAgMzBhMjAgMjAgMCAwMTQwIDAgMjAgMjAgMCAwMTQwIDBxMCAzMC00MCA2MC00MC0zMC00MC02MHoiIGZpbGw9InJlZCIvPjwvc3ZnPg==)
}

.likebtn:hover {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>
0 голосов
/ 30 января 2020

Просто отправьте делегата из верхнего компонента, который прослушивает событие, которое вы создаете в нижнем дочернем элементе. Как то так:

class Parent extends React.Component {
    state = { isChecked: false }

    handleChange = isChecked => this.setState({ isChecked })

    render () {
        const { isChecked } = this.state;

        return (
            <div>
                <Sibling isChecked={isChecked} onChange={this.handleChange}/>
                <Sibling isChecked={isChecked} onChange={this.handleChange}/>
                <Sibling isChecked={isChecked} onChange={this.handleChange}/>
            </div>
        );
    }
}

class Sibling extends React.Component {
    render () {
        const { isChecked, onChange } = this.props;

        return (
            <div>
                <Child isChecked={isChecked} onChange={onChange}/>
            </div>
        );
    }
}


class Child extends React.Component {
    render () {
        const { isChecked, onChange } = this.props;

        return <div onClick={() => onChange(!isChecked)}/>;
    }
}
0 голосов
/ 30 января 2020

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

Также это может помочь Как передать состояние обратно родителю в React?

0 голосов
/ 30 января 2020

Обычный метод для этих ситуаций - поднять состояние до первого общего предка всех компонентов, которым необходимо использовать состояние (т. Е. В данном случае Images), и передать функции состояния и изменения состояния к дочерним компонентам в качестве реквизита. Вы можете проверить это на https://reactjs.org/docs/lifting-state-up.html

...