как добавить вложенные значения в состояние редукционного массива - PullRequest
0 голосов
/ 16 июня 2019

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

В идеале, если бы это было что-то простое:

Псевдокод

state = {
  items:[],
  text:''
}

onSubmit = e => {
 e.preventDefault();
 this.setState({
  items[...this.state.items, this.state.text]
 })
}

Текст будет отображаться в массиве элементов без необходимости обновлениякод.Однако у меня есть кое-что более сложное.

Изображения будут извлечены из редуктора GET_IMAGES, а затем мы используем POST_COMMENT, чтобы оставить комментарий.

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

структура данных при публикации комментария

{
  "id": 244,
  "image_title": "owlman",
  "img_url": "http://re********nncbp****iy.png",
  "created_at": "2019-06-16T18:41:08.890Z",
  "updated_at": "2019-06-16T18:41:08.890Z",
  "user_id": 1,
  "user": {
    "id": 1,
    "googleId": null,
    "username": "El*****",
    "password": "$2*****Ix/fNUhD40***F3GCjO62",
    "email": "e******om",
    "created_at": "2019-06-05T04:50:20.133Z",
    "updated_at": "2019-06-05T04:50:20.133Z"
  },
  "comments": [
    {
      "id": 243,
      "comment_body": "gooseeeeffsfs",
      "created_at": "2019-06-16T19:31:50.129Z",
      "updated_at": "2019-06-16T19:31:50.129Z",
      "user_id": 1,
      "image_id": 244
    },
  ]
}

редуктор

import { GET_IMAGES, POST_COMMENT, DELETE_IMAGE, UPLOAD_IMAGE } from '../actions/types';

const initialState = {
    images:[],

}

export default  (state = initialState, action) => {
    switch (action.type) {
        case GET_IMAGES:
            console.log(action.data);
            return{
                ...state,
                images:action.data
            }

        case DELETE_IMAGE:
            return{
                ...state,
                images: state.images.filter( (img) => img.id !== action.payload)
            }

        case POST_COMMENT:

            const commentnewState = {...state}
            const myComments = commentnewState.images // old images

            const newComments = action.data
            console.log(myComments[0].user.username)
            // tyring to pass new commment, within the images array. unsuccessful as of now.
            return{
                images:[
                    myComments[0],
                    {
                        user:{
                            username:myComments[0].user.username
                        },
                        comments:{
                          comment_body: newComments.commentBody
                        },

                    },

                ]

            }
        default:
            return state;
    }
}

действия

// get images

 export const getImages = () => {
   return (dispatch) => {
     return Axios.get('/images/uploads').then( (response) => {
            const data = response.data;
            dispatch({ 
               type: GET_IMAGES,
               data
             })
        });
    }
}
// post comment

export const postComment = data => {
    return async (dispatch) => {
        return Axios.post('/images/newComment', data).then( (response )=> {
            const newComment = response.data;
            console.log(newComment);
            dispatch({type:POST_COMMENT, data})
        })
    }
}

Комментарии отображаются следующим образом:

commentSubmit = (event, id) => {
   event.preventDefault();
   console.log(this.state.comment_body); // doesn't get console.log
   // note that commentBody is being used for the req.body as well so its called by req.body.commentBody
   const commentBody = this.state.comment_body
   const data = {   
       commentBody,
       id
   }   
   this.props.postComment(data);
   this.setState({
        comment_body: ''
   })

  }
    render(){
       const { img, deleteImg } = this.props

{img.comments.length > 0 ? <Typography style={{ padding:'30px 10px'}}  variant="h6" align="left">Commments </Typography> : null }
{img.comments.length > 0 ? (
    img.comments.map( (comment, i) => (
        <div key={i}>  
            <List>
                <ListItem alignItems="center"> 
                    <Typography color="primary" variant="body1">
                        {comment.comment_body}
                        </Typography>  
                </ListItem>
                <Typography style={{ margin:'0px 15px'}} variant="caption" align="right">{moment(comment.created_at).calendar()}</Typography> 
                <Divider variant="fullWidth" component="li" />
            </List>
        </div>       
    ))
):(
    <div>
        <Typography style={{  padding:'30px 10px'}}>No Commments Yet</Typography>
    </div>
)}

1 Ответ

1 голос
/ 16 июня 2019

Настройте свой бэкэнд-маршрут на Axios.post('/images/newComment', data), чтобы он отвечал обновленным изображением , а не новым комментарием. С обновленным изображением у нас есть соответствующий идентификатор для использования с изображением, когда мы хотим обновить редуктор изображений.

Тогда в вашем редукторе мы можем использовать. map(), чтобы создать новый массив и обновить нужное изображение новым комментарием.

case POST_COMMENT:
    return {
        ...state,
        images: state.images.map((image) => {
            if(image.id == action.data.id){ //assumes action.data.id now is an image id
                return {
                    ...image,
                    comments: [
                     ...image.comments,
                     {
                      comment_body: action.data.commentBody
                     }
                   ]
                }
            } else {
                return image
            }
        })
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...