使用redux将对象添加到数组

时间:2019-06-01 12:35:49

标签: reactjs redux

我在使用redux时遇到问题。 当我使用 store.dispatch( addExpense( {description: "Rent"} ) ); 在我的app.js文件中,它可以正常工作并添加了对象。但是,当我尝试在单独文件中的组件上下文中使用它时,它就没有。控制台不会引发任何错误。 当我在同一组件中使用其他操作(例如“搜索”)时,它可以正常工作。因此,连接没有问题。似乎由于某些原因它无法更改状态。

//ACTIONS

export const addExpense = ( { description="", amount=0 } = {}) => ({
    type: "ADD_EXPENSE",
    expense: {
        description,
        amount
}
})

//REDUCERS
const expenseReducer = ( state = [], action) => {
    switch(action.type) {
        case "ADD_EXPENSE":
            return [...state, action.expense]

        case "EDIT_EXPENSE": //<- this works
            return state.map( (expense) => {
                if (expense.id === action.id) 
                return  {
                    ...expense, ...action.update }
                else return expense
        } )
        default: return state
    }

const filterReducer = ( state = {text:""}, action) => {
    switch(action.type){
        case "FIND_TEXT": //<- this works
            return { ...state, text:action.text }            
        default: return state;
    }
}
//COMPONENT

const AddEx = ( props ) => (
    <div>
        <form onSubmit={(e) => {
            e.preventDefault;
            props.dispatch(addExpense ( {description: document.getElementById("addedEx").value} ))
            console.log(document.getElementById("addedEx").value); 
//it shows the correct value in the console but the state stays unchanged 
        } } >
            <input type="text" id="addedEx"/>
            <button type="submit">submit</button>
        </form>

//SEARACH -> works
        <input
        type="text" value={props.filter.text}
        onChange={(e) => { 
            props.dispatch(findText({text:e.target.value}))
        }}
        />
    </div>
)

2 个答案:

答案 0 :(得分:0)

您要添加值而不是expenses的状态,请执行return [...state.expense, action.expense]

//REDUCERS
const expenseReducer = (state = [], action) => {
  switch (action.type) {
    case 'ADD_EXPENSE':
      return {
        ...state,
        expense: [...state.expense, action.expense]
      };

    case 'EDIT_EXPENSE': //<- this works
      return state.map(expense => {
        if (expense.id === action.id)
          return {
            ...expense,
            ...action.update
          };
        else return expense;
      });
    default:
      return state;
  }
};

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/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/babel-standalone/6.21.1/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.0.3/react-redux.min.js"></script>
<script src="http://wzrd.in/standalone/uuid%2Fv1@latest"></script>
    
<div id="root"></div>

    <script type="text/babel">
      const { Provider, connect } = ReactRedux;
      const { applyMiddleware, createStore, combineReducers } = Redux;
      const ADD_EXPENSE = 'ADD_EXPENSE';

      function addExpense(payload) {
        return { type: ADD_EXPENSE, payload };
      }

      const initialState = {
        expense: [],
      };

      function rootReducer(state = initialState, action) {
        if (action.type === ADD_EXPENSE) {
          return {
            ...state,
            expense: [...state.expense, action.payload]
          };
        }
        return state;
      }

      const store = createStore(rootReducer);

      const mapStateToProps = state => {
        return { expense: state.expense };
      };

      function mapDispatchToProps(dispatch) {
        return {
          addExpense: expense => dispatch(addExpense(expense))
        };
      }

      const ConnectedList = ({ expense, addExpense }) => {
        return (
          <div>
            <ul className="list-group list-group-flush">
              {expense.map(el => (
                <li className="list-group-item" key={el.id}>
                  {`${el.description} - $${el.amount}`}
                </li>
              ))}
            </ul>
          </div>
        );
      };

      const List = connect(
        mapStateToProps,
      )(ConnectedList);

      class ExpenseForm extends React.Component {
        state = {
          description: '',
          amount: 0,
        }

        handleSubmit = (e) => {
          e.preventDefault();

          if (!this.state.description || this.state.amount === 0) {
            return
          }

          const { description, amount } = this.state;

          this.props.addExpense({
            description,
            amount,
            id: uuidv1()
          });

          this.setState({
            description: '',
            amount: 0
          })
        }

        handleInput = (e) => {
          this.setState({
            [e.target.name]: e.target.value
          })
        }

        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              <input name="description" placeholder="Description" onChange={this.handleInput} value={this.state.description} />
              <input type="number" name="amount" placeholder="Amount" onChange={this.handleInput} value={this.state.amount} />
              <input type="submit" />
            </form>
          )
        }

      }

      const Form = connect(null, mapDispatchToProps)(ExpenseForm);

      class App extends React.Component {
        render() {
          return (
            <div>
              <List />
              <Form />
            </div>
          );
        }
      }
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
    </script>

答案 1 :(得分:0)

我找到了解决方案。它不起作用,因为 e.preventDefault缺少()。从e.preventDefault更改为e.preventDefault()的简单更改即可解决。愚蠢的错误。