作为道具传递的功能不是功能

时间:2020-06-05 07:41:48

标签: javascript reactjs react-redux react-props

我正在尝试将名为addtodo的函数作为类的道具传递。我已经通过了如下功能

export class Todo extends Component {
    constructor(props) {
        super(props);
        this.state = {todos:[]};

        this.addtodo = this.addtodo.bind(this);
        this.deleteTodo = this.deleteTodo.bind(this);

      }
    componentDidMount(){
axios.get('https://jsonplaceholder.typicode.com/posts').then(res=>{
    this.setState({
       todos:res.data

    })
})
    }
  addtodo(todo){
        todo.id=Math.floor(Math.random()*100)
        todo.completed=true
       const todos=[...this.state.todos,todo]
       this.setState({
         todos:todos
       })
         }
    deleteTodo(id){
        const todo=this.state.todos.filter(todo=>{
         return(
            todo.id!==id
         )
        }
            )
            this.setState({
                todos:todo
            })
    }
    render() {
        return (
            <div>
           <h1 className="center-align"> Todos</h1>
                   <Todolist todos={this.state.todos} deleteTodo={this.deleteTodo}/>
                   <Addtodo addtodo={this.addtodo}/>
            </div>
        )
    }
}

export default Todo

在Addtodo.js中,我正在使用以下功能作为道具

 class Addtodo extends Component {
      constructor(props) {
    super(props);
    this.state = { title:'',
    body:''
};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);

  }

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

    handleSubmit(e){
        e.preventDefault()
        this.props.addtodo(this.state)
        this.setState({
            title:'',
            body:''
        })
        }


    render() {
        return (
            <form className="col s12" onSubmit={this.handleSubmit}>
            <div className="row">
              <div className="input-field col s6">
                <input placeholder="Add title" id="title" type="text" className="validate" onChange={this.handleChange}/>
              </div>
              <div className="input-field col s6">
                <input placeholder="Add body" id="body" type="text" className="validate" onChange={this.handleChange}/>
              </div>
              <button type="submit">Submit</button>
              </div>
              </form>
        )
    }
}

export default Addtodo

但是我收到错误Uncaught TypeError: this.props.addtodo is not a function。我也检查了拼写错误,但无法弄清为什么它不起作用。而如果我将它作为道具传递给另一个类,并简单地记录一个问候消息,则它正在工作。

3 个答案:

答案 0 :(得分:1)

我成功地在stackblitz上运行了您的代码,并且没有错误

我发现了另一个错误,

之前

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

之后

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

check stackblitz demo

提示: 因为我没有足够的分数,所以我无法添加评论,只能由编辑者回答

更新:

之前:

function App() {
  return (
    <BrowserRouter>
      <div className="container">
        <Addtodo />
        <Switch>
          <Route exact path="/" component={Todo} />
          <Route path="/:id" component={Task} />
        </Switch>
      </div>
    </BrowserRouter>
  );
}

export default App;

function App() {
  return (
    <BrowserRouter>
      <div className="container">
        <Switch>
          <Route exact path="/" component={Todo} />
        </Switch>
      </div>
    </BrowserRouter>
  );
}

render(<App/>, document.getElementById('root'))

请检查代码不超过一个Addtodo吗?

答案 1 :(得分:0)

您没有在类中注册函数addtodo,因此this.addtodo未绑定到函数addtodo而是为空。因此,您的错误。

请参见React docs - Handling events中的示例:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

第6行注意,该函数首先绑定到该类,然后可以通过this.<function_name>对其进行定义和调用。

在您的代码中,构造函数不见了:

this.addtodo = this.addtodo.bind(this);

在此之前,您无法调用this.addtodo,因为它没有绑定到this,因此您的错误是this.props.addtodo不是函数。

答案 2 :(得分:0)

我猜你在构造函数中缺少绑定。在您的构造函数中,您需要像这样声明它

this.addtodo = this.addtodo.bind(this);

已编辑**

我已经测试了代码,似乎没有错误,

Todo.js

import React, { Component } from "react";
import axios from "axios";

import Addtodo from "./Addtodo";

export class Todo extends Component {
  state = {
    todos: [],
  };
  componentDidMount() {
    axios.get("https://jsonplaceholder.typicode.com/posts").then((res) => {
      this.setState({
        todos: res.data,
      });
    });
  }
  addtodo = (todo) => {
    todo.id = Math.floor(Math.random() * 100);
    todo.completed = true;
    const todos = [...this.state.todos, todo];
    this.setState({
      todos: todos,
    });
  };

  render() {
    console.log(this.state.todos);
    return (
      <div>
        <h1 className="center-align"> Todos</h1>
        <Addtodo addtodo={this.addtodo} />
      </div>
    );
  }
}

export default Todo;

Addtodo.js

import React, { Component } from "react";
class Addtodo extends Component {
  constructor(props) {
    super(props);
    this.state = { title: "", body: "" };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

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

  handleSubmit(e) {
    e.preventDefault();
    this.props.addtodo(this.state);
    this.setState({
      title: "",
      body: "",
    });
  }

  render() {
    return (
      <form className="col s12" onSubmit={this.handleSubmit}>
        <div className="row">
          <div className="input-field col s6">
            <input
              placeholder="Add title"
              id="title"
              type="text"
              className="validate"
              onChange={this.handleChange}
            />
          </div>
          <div className="input-field col s6">
            <input
              placeholder="Add body"
              id="body"
              type="text"
              className="validate"
              onChange={this.handleChange}
            />
          </div>
          <button type="submit">Submit</button>
        </div>
      </form>
    );
  }
}

export default Addtodo;