0

I have a .map function in a component:

let recentItemsMarkup = loading ? (
      <p>Items are loading...</p>
    ) : (
      items.map(item => (
        <ShoppingItem
          key={item._id}
          id={item._id}
          name={item.name}
          createdAt={item.date}
        />
      ))
    );

When I post an item, sometimes -not always- it duplicates on the view, but not in Database. DB is working properly, but somehow, after I post an item, it is not always sets the items properly, here are the action and the reducer:

  //post item
  export const postItem = newItem => dispatch => {
  dispatch({ type: LOADING_UI });
  axios
    .post("http://localhost:5000/api/items", newItem)
    .then(res => {
      dispatch({
        type: POST_ITEM,
        payload: res.data
      });
    })
    .catch(err => {
      dispatch({
        type: SET_ERRORS,
        payload: err.response.data
      });
    });
};

and the reducer:

const initialState = {
  items: [],
  item: {},
  loading: false
};

export default (state = initialState, action) => {
  switch (action.type) {
    case LOADING_ITEMS:
      return {
        ...state,
        loading: true
      };
    case GET_ITEMS:
      return {
        ...state,
        items: action.payload,
        loading: false
      };
    case POST_ITEM:
      return {
        ...state,
        items: [action.payload, ...state.items]
      };

    case DELETE_ITEM:
      return {
        ...state,
        items: state.items.filter(item => item._id !== action.payload)
      };
    default:
      return state;
  }
};

I checked the Ids and Database, everything is ok, ids are unique vs. Why this happening?

screenshot

and also Shopping Item component:

class ShoppingItem extends Component {


  render() {
    const { authenticated } = this.props.user;
    const { name, createdAt, classes, id } = this.props;
    const deleteButton = authenticated ? (
      <DeleteItem id={id} />
    ) : null;
    return (
      <Card className={classes.card}>
        <CardContent>
          <Typography variant="body1" color="textPrimary">
            {this.props.id}
          </Typography>
          <Typography variant="body1" color="textPrimary">
            {name}
          </Typography>
          {deleteButton}
          <Typography color="textSecondary">
            {dayjs(createdAt).format("h:mm a, MMM DD YYYY")}
          </Typography>
        </CardContent>
      </Card>
    );
  }
}

ShoppingItem.propTypes = {
  name: PropTypes.string.isRequired,
};

const mapStateToProps = state => ({
  user: state.user
});

const actionsToProps = {
  deleteItem
};

export default connect(
  mapStateToProps,
  actionsToProps
)(withStyles(styles)(ShoppingItem));
2
  • try dispatching GET_ITEMS each time you post item and show what's going on! Commented Nov 26, 2019 at 14:26
  • It is already doing that in the code: handleSubmit = event => { event.preventDefault(); const newItem = { name: this.state.name, handler: this.props.user.user.name }; this.props.postItem(newItem); this.props.getItems(); }; Commented Nov 26, 2019 at 15:13

3 Answers 3

1

It seems like your backend returns an array of items together with the new one, so in that case you'd just set them on the state, instead of adding to existing items:

case POST_ITEM:
      return {
        ...state,
        items: action.payload
      };
Sign up to request clarification or add additional context in comments.

1 Comment

I tried many versions including you but still, get errors occasionally. I did not get the logic of, how it works only sometimes. Because if the id is unique, db is ok how it sometimes duplicate just on the view? It seems somehow it pushes the new Item and all the items(including the new item) at the same time
0

It is because of

case POST_ITEM: return { ...state, items: [action.payload, ...state.items] };

just send the item which needs to add & then handle insertion at backend.

Comments

0

Ok, I solved the problem, My failure is, I added "getItems" to "postItem" function which causes duplication because when I post an item it already refreshes the page and loads the Items from componentDidMount method. So it seems I didn't understand the logic very well, which is when a state or props change, the page refreshes automatically.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.