如何将嵌套值附加到redux数组状态

时间:2019-06-16 19:59:29

标签: reactjs redux

我正在向图像发布评论,我希望能够获取新的评论状态而不必刷新页面以查看 new 评论。

理想情况是这样简单:

伪代码

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

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

文本将显示在items数组中,而无需刷新代码。但是,我有一些更复杂的东西。

图像将从GET_IMAGES缩减器中获取,然后我们使用POST_COMMENT发表评论。

理想情况下,我试图将newComment追加到images数组,并且再次无需刷新页面以查看评论。

发布评论时的数据结构

{
  "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 个答案:

答案 0 :(得分:1)

Axios.post('/images/newComment', data)上配置后端路由,以便它响应更新后的图像,而不是新注释。对于更新的图像,当我们要更新Images Reducer时,我们具有与该图像一起使用的对应ID。

然后在减速器中,我们可以使用。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
            }
        })
    }