TypeError: Cannot read properties of undefined (reading 'push')

来源:6-4 使用Redux-thunk 中间件实现ajax数据请求

explore999

2022-04-17

为什么我一点击输入框, 什么都输入不了, 报错: TypeError: Cannot read properties of undefined (reading ‘push’)

reducer.js

import {  INIT_LIST_ACTION, CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes'
const defaultState = {
  inputValue: '',
  list: []
}

export default (state = defaultState, action) => {
  
  if (action.type === CHANGE_INPUT_VALUE) {
    const newState = JSON.parse(JSON.stringify(state));
    newState.list = action.data;
    return newState;
  }
  if (action.type === INIT_LIST_ACTION) {
    const newState = JSON.parse(JSON.stringify(state));
    newState.list = action.data;
    return newState;
  }

  if (action.type === ADD_TODO_ITEM) {
    const newState = JSON.parse(JSON.stringify(state));
    newState.list.push(newState.inputValue);
    newState.inputValue = '';
    // console.log(newState);
    return newState;
  }


  if (action.type === DELETE_TODO_ITEM) {
    const newState = JSON.parse(JSON.stringify(state));
    // 删除对应下标的1个项
    newState.list.splice(action.index, 1);

    // console.log(newState);
    return newState;
  }

  // console.log(state, action);
  return state;
}

TodoList.js

import React, { Component, Fragment } from "react";
import TodoItem from './TodoItem';
import axios from 'axios'
import './style.css';

import store from "./store";
import { getInputChangeValue, getAddItemAction, getDeleteItemAction, initListAction } from './store/actionCreators'
import TodoListUI from './TodoListUI'

class TodoList extends Component {  
    constructor(props) {
        super(props);
        this.state = store.getState();
        // console.log(store.getState());
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        // store.subscribe(this.handleStoreChange);
        this.handleBtnClick = this.handleBtnClick.bind(this);
        this.handleItemDelete = this.handleItemDelete.bind(this)
    }
    render() {
        return (
            <TodoListUI
                inputValue = {this.state.inputValue}
                list = {this.state.list}
                handleInputChange = {this.handleInputChange}
                handleBtnClick = {this.handleBtnClick}
                handleItemDelete = {this.handleItemDelete}
             />
        )
    }

    componentDidMount() {
        store.subscribe(this.handleStoreChange);
        axios.get('/list.json').then((res) => {
            const data = res.data;
            const action = initListAction(data);
            // console.log(res);
            // console.log(action);
            store.dispatch(action); 

        })
    }

    handleInputChange(e) {
        // console.log(e.target.value)
        const action = getInputChangeValue(e.target.value);
        store.dispatch(action);
    }
    handleStoreChange(e) {
        // console.log('store changed')
        this.setState(store.getState());
    }
    handleBtnClick() {
        const action = getAddItemAction();
        store.dispatch(action);
    }
    handleItemDelete(index) {
        // alert(index); //function ImageBitmapRenderingContext() { [native code] } ??
        const action = getDeleteItemAction(index);
        store.dispatch(action);
    }
    

}
export default TodoList;

TodoListUI.js

import React from "react";
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
import { Input, Button, List } from 'antd';

const TodoListUI = (props)  =>  {
  return (
    <div style={{marginTop: '10px', marginLeft: '10px'}}>
      <div>
        <Input 
          value={props.inputValue} 
          placeholder="todo" 
          style={{width: '300px', marginRight: '10px'}} 
          onChange={props.handleInputChange}
        />
        <Button type="primary" onClick={props.handleBtnClick}>提交</Button>
      </div>
      <List
          style={{marginTop: '10px', width: '300px'}}
          bordered
          dataSource={props.list} 
          renderItem={(item, index) => <List.Item onClick={ (index) => {props.handleItemDelete(index)}}>{item}</List.Item>}
      />
    </div>
  )
}

// class TodoListUI extends Component {
//   render() {
//     return (
//         <div style={{marginTop: '10px', marginLeft: '10px'}}>
//           <div>
//             <Input 
//               value={this.props.inputValue} 
//               placeholder="todo" 
//               style={{width: '300px', marginRight: '10px'}} 
//               onChange={this.props.handleInputChange}
//             />
//             <Button type="primary" onClick={this.props.handleBtnClick}>提交</Button>
//         </div>
//         <List
//             style={{marginTop: '10px', width: '300px'}}
//             bordered
//             dataSource={this.props.list} 
//             renderItem={(item, index) => <List.Item onClick={ (index) => {this.props.handleItemDelete(index)}}>{item}</List.Item>}
//         />
//       </div>
//     )
//   }
// }
export default TodoListUI;

actionCreators.js

import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes'
export const getInputChangeValue = (value) => ({
  type: CHANGE_INPUT_VALUE,
  value
});

export const getAddItemAction = (value) => ({
  type: ADD_TODO_ITEM
});

export const getDeleteItemAction = (index) => ({
  type: DELETE_TODO_ITEM,
  index
});

export const initListAction = (data) => ({
  type: INIT_LIST_ACTION,
  data
});

actionTypes.js

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
export const INIT_LIST_ACTION = 'init_list_action';
写回答

1回答

Dell

2022-04-24

const newState = JSON.parse(JSON.stringify(state));

打印一下 newState ,看下打印出来的内容

0
0

React零基础入门到实战,完成企业级项目简书网站开发

主流新技术 React-redux,React-router4,贯穿基础语法

5275 学习 · 2496 问题

查看课程