简体   繁体   中英

How to delete a specific element from an array in the redux store

I am new to to redux and react. Still doing simple tutorials. I managed to create 2 simple components; one that outputs on the screen (as a list) whatever is in the array in the redux store, and the other component contains a button and a textfield which basically adds to that array in the store.

I would like to add a feature that will enable me to delete a specific entry in the list depending on what the user clicked on. I am thinking of creating a <button> next to each <li> tag that gets rendered as it loops through the array, and these buttons will correspond to the respective list elements. But I'm not sure how to do that.

I've tried creating a button when each <li> tag gets created but I was getting an error on the console stating that each element in a list needs a unique ID. I then decided to create another array in my store called buttons which will contain a unique id as well as the id of the list but it got out of hand. I think I might be overcomplicating this. This is what I have at the moment:

Components: List.jsx (responsible for outputting the list)

import React from 'react'
import { connect } from "react-redux";

const ListComp = ({ lists }) => (
    <div>    
        <ul>
            {console.log(lists)}
            {lists.map( element => (
                    <li key={element.id}>
                        {element.titleToBeAddedToList}
                    </li>
            ))}
        </ul>
    </div>
)

const mapStateToProps = state => {
    return {
        lists: state.lists
    };
}
const List = connect(mapStateToProps)(ListComp)

export default List;

SubmitButton.jsx (responsible for outputting the button and textfield)

import React from 'react'
import { connect } from "react-redux";
import uuidv1 from "uuid";
import { addList } from "../actions/index";
import { addButton } from "../actions/index"

function mapDispatchToProps(dispatch){
    return {
        addlist: article => dispatch(addList(article)),
        addbutton: idOfButton => dispatch(addButton(idOfButton))
      };
}

class Submit extends React.Component{

    constructor(){
        super();
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);        
    }

    handleChange(event) {
        this.setState({ [event.target.id]: event.target.value });
    }

    handleSubmit(event) {
        event.preventDefault();
        const {titleToBeAddedToList} = this.state;
        const id = uuidv1();
        const button_id = uuidv1();
        //Dispatching the action:
        this.props.addlist({ titleToBeAddedToList, id });
        this.props.addbutton({id, button_id});        
        //Once we've dispatched an action, we want to clear the state:
        this.setState({ titleToBeAddedToList: "" });
    }

    render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label htmlFor="title">Title</label>
              <input
                type="text"
                className="form-control"
                id="titleToBeAddedToList"
                onChange={this.handleChange}
              />
            </div>
            <button type="submit" className="btn btn-success btn-lg">
              SAVE
            </button>
          </form>
        );
      }
}

const SubmitButton = connect(null, mapDispatchToProps)(Submit)

export default SubmitButton;

Reducers:

const initialState = {
lists: [],
buttons: []
};

function rootReducer (state = initialState, action) {
    if(action.type === "ADD_LIST" ){
        return Object.assign({}, state, {
            lists: state.lists.concat(action.payload)
          });
    } else if(action.type === "ADD_BUTTON"){
        return Object.assign({}, state, {
            buttons: state.lists.concat(action.payload)
          });
    } else if(action.type === "DELETE_FROM_LIST"){
        //.....//
    }
    return state;
}

export default rootReducer;

Action:

    export function addList(payload) {
    return { type: "ADD_LIST", payload }
};

export function addButton(payload){
  return {type: "ADD_BUTTON", payload }
}

export function deleteList(payload){
  return { type: "DELETE_FROM_LIST", payload }
}

Store:

import { createStore } from "redux";
import rootReducer from "../reducers/index";

const store = createStore(rootReducer);

export default store;
else if (action.type === "DELETE_FROM_LIST") {
  return Object.assign({}, state, {
    buttons: state.lists.filter(item => (item.id !==action.payload))
  });
}

you can use filter() for delete.

You can use Math.random() as an unique key identifier, if the button is click it will call action deleteItem with the ID, action is bound to reducer pass on the ID, you can then use the ID to indentify elements and remove it in the list.

import React from 'react'
import { connect } from "react-redux";
import { deleteItem } from './actions';

const ListComp = ({ lists }) => (
   <div>    
       <ul>
          {console.log(lists)}
          {lists.map( element => (
             <li key={Math.random()} key={element.id}>
                 {element.titleToBeAddedToList}
                  <button onClick={() => deleteItem(element.id)}>X</button>
              </li>
                ))}
       </ul>
    </div>
)

const mapStateToProps = state => {
   return {
      lists: state.lists
    };
}
const List = connect(mapStateToProps, {deleteItem})(ListComp) // Make it available to component as props

export default List;



Action:

export function deleteElement(id) {
  return function(dispatch) {
    return dispatch({type: "DELETE_FROM_LIST", payload: id})
  }
}



Reducer:

 case 'DELETE_FROM_LIST': {
  const id = action.payload;
  return {
    ...state,
    list: state.list.filter(item => item.id !== id)
  }
}

This is a minimal working react-redux example containing all the pieces to delete an item from an array in redux store.

 // reducer.js const reducer = (state, action) => { switch (action.type) { case 'DELETE': return state.filter(item => ( item.id !== action.payload.id )) default: return state; } } // Item.js const Item = ({id, onClick, label}) => ( <li> {label} <button onClick={ () => onClick(id) }> delete </button> </li> ) // ListContainer.js const mapStateToProps = state => ({ items: state }) const ListContainer = ReactRedux.connect(mapStateToProps)(class extends React.Component { handleDelete = id => { const { dispatch } = this.props; dispatch({ type: 'DELETE', payload: { id } }) } render() { const { items } = this.props; return items.map(({id, label}) => ( <Item label={label} id={id} onClick={this.handleDelete} /> )) } }) // Main.js const initialState = [ { id: 1, label: 'item 1' }, { id: 2, label: 'item 2' }, { id: 3, label: 'item 3' }, { id: 4, label: 'item 4' } ] const store = Redux.createStore(reducer, initialState); class App extends React.Component { render(){ return ( <ReactRedux.Provider store={store}> <ListContainer /> </ReactRedux.Provider> ); } } ReactDOM.render(<App />, document.getElementById('root')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.1/react-redux.js"></script> <div id="root"></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM