Alex
Alex

Reputation: 323

Redux: how to dispatch a unique object key (unique Id, instead of hard coded)

I have a Redux action called makePost which receives data that looks like this:

{
  comment: false,
  comments_text: "",
  like: 0,
  name: "test"
}

The action then pushes the data to Firebase Realtime Database. It then dispatches another action (called post) to update the current React state with the data and includes a unique response id (id: response.key). It looks like this:

export const makePost = (postObject) => {
    return (dispatch, getState) => {
        const uid = getState().userId;
        database
            .ref(`users/${uid}/posts`)
            .push(postObject)
            .then((response) => {
                dispatch(
                    post({
                        key: uid,
                        id: response.key,
                        ...postObject,
                    })
                )
            })
    }
}

The post dispatch action looks like this:

export const post = (post) => {
    return {
        type: "POST",
        payload: {
            key: post.key,
            handle: "PLACEHOLDER",
            posts: {
                postKey: {
                    name: post.name,
                    like: post.like,
                    comment: false,
                    comments_text: []
                }    
            }
        }
    }
}

My question is regarding the id: response.key. When I dispatch post, I want postKey (object key) to be the unique response id (id: response.key), not hard coded as postKey. Is there a way to dynamically do this? I tried writing it as post.id but this doesn't work.

For reference, the POST reducer looks like this:

const postsReducer = (state = [], action) => {
    switch (action.type){
        case POST:
            return [...state, action.payload];

This is what my React state looks like currently, notice the previous data (object 1) has the unique response Ids, but the latest post (object 2) is hard coded as postKey:

enter image description here

Upvotes: 0

Views: 360

Answers (1)

romellem
romellem

Reputation: 6491

You want to use a computed property name on the object that post is returning.

The object initializer syntax also supports computed property names that allows you to put an expression in brackets [], that will be computed and used as the property name.

let some_key = 'abc';
let obj = {
  [some_key]: 123
};
// obj = { abc: 123 }

So in your case, use [post.id] as this computed property:

export const post = (post) => {
  return {
    type: "POST",
    payload: {
      key: post.key,
      handle: "PLACEHOLDER",
      posts: {
        // Assumes that `post.id` exists
        [post.id]: {
          name: post.name,
          like: post.like,
          comment: false,
          comments_text: [],
        },
      },
    },
  };
};

Upvotes: 1

Related Questions