smooth97
smooth97

Reputation: 91

How to update an array using redux

I'm using react-redux to create a simple CRUD app. The ability to import titles and descriptions from the input, store them in the array, and delete them has been implemented, but the ability to modify them is difficult and asks for help.

action.js

export const addPosting = (title, description) => {
    return {
        type: ADD_POSTING,
        post: {
            id: nextId++,
            title,
            description
        }
    };
}

export const updatePosting = (payload) => {
    return {
        type: UPDATE_POSTING,
        payload
    }
}

export const deletePosting = (id) => {
    return {
        type: DELETE_POSTING,
        id
    }
}

postReducer.js

const initialState = [{
    id: 1,
    title: ' This is First Post',
    description: 'Lorem ipsum dolor sit amet consectetur, adipisicing elit.',
}]

const posts = (state = initialState, action) => {
    switch (action.type) {
        case ADD_POSTING:
            return state.concat(action.post);
        case DELETE_POSTING:
            return state.filter(post => post.id !== action.id);
        case UPDATE_POSTING:
            return // help
        default:
            return state;
    }
};

The method that I tried was not modified.

case UPDATE_POSTING:
            return state.map(post => post.id === action.id ? {
                ...action.post,
            } :
            post
            )

action state

form.jsx

import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { updatePosting } from '../store/actions';

const Modal = ({ post, modal, close }) => {
  // update redux
  const posts = useSelector(state => state.posts);
  const dispatch = useDispatch();

  const onUpdate = (title, description) =>
    dispatch(updatePosting(title, description));

  // inputs
  const [inputs, setInputs] = useState({
    title: post.title,
    description: post.description,
  });

  const { title, description } = inputs;

  const onChange = e => {
    const { value, name } = e.target;
    setInputs({
      ...inputs,
      [name]: value,
    });
  };

  const onSubmit = e => {
    e.preventDefault();
    onUpdate(title, description);
    setInputs({
      title: post.title,
      description: post.description,
    });
  };

  return (
    <React.Fragment>
      {modal ? (
    <React.Fragment>
      <div className="modal-container">
        <form className="modal" onSubmit={onSubmit}>
          <div className="title">
            <input
              className="titleInput"
              type="text"
              name="title"
              required
              value={title}
              onChange={onChange}
            />
            <button onClick={close}>x</button>
          </div>
          <div className="des">
            <textarea
              name="description"
              className="modal-des"
              cols="30"
              rows="10"
              required
              value={description}
              onChange={onChange}
            ></textarea>
          </div>
          <button onSubmit={onSubmit}>submit</button>
        </form>
      </div>
    </React.Fragment>
      ) : null}
    </React.Fragment>
  );
};

export default Modal;

Thank you for your help in solving this problem.

Upvotes: 1

Views: 3429

Answers (4)

vipul patel
vipul patel

Reputation: 736

There are couple of error in you code. Your update call does not provide ID for which you are updating: so first pass the ID of the post which you are changing.

const onUpdate = (id, title, description) =>
dispatch(updatePosting(id, title, description));

Then in your reducer :

 case UPDATE_POSTING:
    // find the id which are trying to update with new title and description
    const filtered = state.filter((post) => post.id === action.payload.id);
    filtered.title= action.payload.title;
    filtered.description= action.payload.description;
    return filtered; //according your need post this

Upvotes: 0

N. Henoc HOUNSA
N. Henoc HOUNSA

Reputation: 169

resp :

case UPDATE_POSTING:
            return state.map((post, index) => {
                if (post.id === action.payload.id) {
                    return Object.assign({}, post, {
                        title: action.payload.title,
                        description: action.payload.description,
                        ...
                    })
                }

                return post
            })

in your action :

updatePosting = (post) => ({
    type: UPDATE_POSTING,
    payload: {
        title: post.title,
        description: post.description
    }
})

Hope it helps !

Upvotes: 0

Andy
Andy

Reputation: 63589

It sounds like you need do two operations:

1) filter out all the posts that don't have the updated post's id.

2) Add the new post to the filtered array and return it as new state.

Note that to do this you will need to send the id as an argument when you call updatePosting.

case UPDATE_POSTING: {
  const filtered = state.filter((post) => post.id !== action.post.id);
  return [ ....filtered, action.post ];
}

Upvotes: 1

Maxime Girou
Maxime Girou

Reputation: 1570

Your problem come from the way you use the action object. It containing your post as payload property as you put it in the action method :

export const updatePosting = (payload) => {
return {
    type: UPDATE_POSTING,
    payload
}

}

So, your post can be access with action.payload

case UPDATE_POSTING:
   return state.map(post => {
     if(post.id === action.payload.id){
        post = action.payload;
     }
   }
  )

Upvotes: 0

Related Questions