【问题标题】:this.state.todos.map is not a function, React.jsthis.state.todos.map 不是函数,React.js
【发布时间】:2018-12-22 18:46:51
【问题描述】:

我正在制作一个简单的 Todo 列表,其中包含一个容器 App 组件以及一个子 Todo 无状态功能组件。当我创建一个新的 todo 时,我希望它被添加到我在父组件状态中定义的 todos 数组中。但是,当我这样做时,我收到错误:Uncaught TypeError: this.state.todos.map is not a function。有人可以帮我理解这是为什么。

这里是父组件:

class App extends Component {
  constructor(props){
  	super(props);
  	this.state = {
  		input: '',
  		todos: [
  			'buy milk',
  			'buy eggs',
  			'take out trash'
  		]
  	};
  	this.handleSubmit=this.handleSubmit.bind(this);
  	this.handleChange=this.handleChange.bind(this);
  }

  handleSubmit(e){
  	let value = this.state.input;
  	let todos = this.state.todos;
  	let newTodos = todos.push(value);
  	this.setState({todos: newTodos, input: ''});

  }

  handleChange(e){
  	this.setState({input: e.target.value})
  }


  render() {
  	let todolist = this.state.todos.map((value, index) => {
  		return(
	  		<ul>
	  			<Todo value={value} />
	  		</ul>
  		)
  	})
    return (
      <div>
      <h1>My Todo list</h1>
      	<form onSubmit={this.handleSubmit}>
      		<input 
      			type='text'
      			onChange={this.handleChange} 
      			value={this.state.input}
      			/>
      		<input type='submit'/>
      	</form>
      {todolist}
      </div>
    );
  }
}

这是子组件:

let Todo = (props) => {
	return(
		<li>{props.value}</li>
	)
};

【问题讨论】:

    标签: javascript reactjs react-native react-redux jsx


    【解决方案1】:

    let newTodos = todos.push(value); 的值将是数组的长度,即3。当您将状态中的todos 更新为此您将收到错误消息。

    您需要使用preventDefault 防止form 的默认行为(即重新加载浏览器),您可以像这样添加待办事项以避免todos 数组的突变:

    handleSubmit(e) {
      e.preventDefault();
    
      this.setState(previousState => {
        return {
          todos: [...previousState.todos, previousState.input],
          input: ""
        };
      });
    }
    

    【讨论】:

    • 结合e.preventDefault(),这行得通,谢谢!
    • @MiddleZ 啊,我错过了它是表单的一部分。我更新了答案。不客气!
    【解决方案2】:

    只是为了添加一个改进。目前你有这个:

    let todolist = this.state.todos.map((value, index) => {
      return (<ul>
        <Todo value={value}/>
      </ul>)
    })
    

    它将为每个待办事项呈现一个 UL,您的 HTML 将如下所示:

    <ul><li>buy milk</li></ul>
    <ul><li>buy eggs</li></ul>
    <ul><li>take out trash</li></ul>
    

    你可以这样做:

    render() {
      let todolist = this.state.todos.map((value, index) => {
      return <Todo value={value}/> // Return only the todo, not the UL
    })
    return (<div>
      <h1>My Todo list</h1>
      <form onSubmit={this.handleSubmit}>
        <input type='text' onChange={this.handleChange} value={this.state.input}/>
        <input type='submit'/>
      </form>
      <ul>{todolist}</ul> // UL here
    
    </div>);}
    }
    

    您将渲染单个 UL:

    <ul>
      <li>buy milk</li>
      <li>buy eggs</li>
      <li>take out trash</li>
    </ul>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 2021-10-24
      • 1970-01-01
      • 2023-01-09
      • 2015-01-21
      • 2020-06-12
      • 1970-01-01
      • 2023-02-23
      相关资源
      最近更新 更多