简体   繁体   English

Function 作为道具传递,而不是 function

[英]Function passed as props not a function

I am trying to pass a function named addtodo as a props from a class.我试图通过一个名为 addtodo 的 function 作为 class 的道具。 I have passed the function as below我已经通过了 function 如下

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

And in Addtodo.js, I am using the function as props as below在 Addtodo.js 中,我使用 function 作为道具,如下所示

 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

But I am getting the error Uncaught TypeError: this.props.addtodo is not a function .但我收到错误Uncaught TypeError: this.props.addtodo is not a function I checked for spelling error as well but could not get why this is not working.我也检查了拼写错误,但不明白为什么这不起作用。 Whereas if I pass it as a props to another class and simply log a hello message it is working.而如果我将它作为道具传递给另一个 class 并简单地记录一个它正在工作的 hello 消息。

I successfully run your code on the stackblitz, and there are no errors我在 stackblitz 上成功运行了你的代码,没有错误

and i found another bug,我发现了另一个错误,

before

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

after

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

check stackblitz demo检查 stackblitz 演示

tip: Because i don't have enough points, so i cannot add comments, can only editor answer提示:因为我的积分不够,所以不能加评论,只能编辑回答

update:更新:

before:前:

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'))

Please check the code is not more than one Addtodo?请检查代码是不是多个Addtodo?

You're not registering the function addtodo in the class, thus this.addtodo is not bound to your function addtodo but instead to null. You're not registering the function addtodo in the class, thus this.addtodo is not bound to your function addtodo but instead to null. Hence your error.因此你的错误。

See this example from React docs - Handling events :请参阅React 文档中的此示例 - 处理事件

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')
);

Notice on line 6 the function is first bound to the class, then it can be defined and called through this.<function_name> .注意第 6 行 function 首先绑定到 class,然后可以通过this.<function_name>定义和调用它。

In your code you're missing in the constructor:在您的代码中,您在构造函数中缺少:

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

Until so, you cannot call this.addtodo , for it's not bound to this , thus your error that this.props.addtodo is not a function.在此之前,您不能调用this.addtodo ,因为它没有绑定到this ,因此您的错误是this.props.addtodo不是 function。

You're missing binding in your constructor I guess.我猜你的构造函数中缺少绑定。 In your constructor, you need to declare it like this在您的构造函数中,您需要像这样声明它

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

Edited **已编辑**

I have tested the code and seems like there was no error,我已经测试了代码,似乎没有错误,

Todo.js 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 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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