React失败的prop类型:没有onChange处理函数的值

时间:2019-03-10 04:40:00

标签: javascript reactjs axios

这是我的while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { done = false; } if (e.type = SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_w: SDL_RenderFillRect(renderer, &player); player.y -=SPEED; draw(); break; case SDLK_s: SDL_RenderFillRect(renderer, &player); player.y +=SPEED; draw(); break; default: break; } } } 组件:

  

Form.jsx

form

这是我的import React, { Component } from 'react'; import axios from 'axios'; import { Redirect } from 'react-router-dom'; class Form extends Component { constructor (props) { super(props); this.state = { formData: { restaurant: '', username: '', email: '', password: '' } }; this.handleUserFormSubmit = this.handleUserFormSubmit.bind(this); this.handleFormChange = this.handleFormChange.bind(this); }; componentDidMount() { this.clearForm(); }; componentWillReceiveProps(nextProps) { if (this.props.formType !== nextProps.formType) { this.clearForm(); }; }; clearForm() { this.setState({ formData: {restaurant: '', username: '', email: '', password: ''} }); }; handleFormChange(event) { const obj = this.state.formData; obj[event.target.name] = event.target.value; this.setState(obj); }; handleUserFormSubmit(event) { event.preventDefault(); const formType = this.props.formType const data = { restaurant: this.state.formData.restaurant, email: this.state.formData.email, password: this.state.formData.password }; if (formType === 'register') { data.username = this.state.formData.username }; const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/${formType}`; axios.post(url, data) .then((res) => { this.clearForm(); this.props.loginUser(res.data.auth_token); }) .catch((err) => { console.log(err); }); }; render() { if (this.props.isAuthenticated) { return <Redirect to='/' />; }; return ( <div> {this.props.formType === 'Login' && <h1 className="title is-1">Log In</h1> } {this.props.formType === 'Register' && <h1 className="title is-1">Register</h1> } <hr/><br/> <form onSubmit={(event) => this.handleUserFormSubmit(event)}> {this.props.formType === 'Register' && <div className="field"> <input name="restaurant" className="input is-medium" type="text" placeholder="Enter your restaurant name" required value={this.state.formData.restaurant} onChange={this.props.handleFormChange} /> </div> } <div className="field"> <input name="username" className="input is-medium" type="text" placeholder="Enter a username" required value={this.state.formData.username} onChange={this.props.handleFormChange} /> </div> <div className="field"> <input name="email" className="input is-medium" type="email" placeholder="Enter an email address" required value={this.state.formData.email} onChange={this.props.handleFormChange} /> </div> <div className="field"> <input name="password" className="input is-medium" type="password" placeholder="Enter a password" required value={this.state.formData.password} onChange={this.props.handleFormChange} /> </div> <input type="submit" className="button is-primary is-medium is-fullwidth" value="Submit" /> </form> </div> ) }; }; export default Form; 组件:

  

App.jsx

app

这是显示的错误控制台:

import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import axios from 'axios';

import UsersList from './components/UsersList';
import About from './components/About';
import NavBar from './components/NavBar';
import Form from './components/Form';
import Logout from './components/Logout';
import UserStatus from './components/UserStatus';


class App extends Component {
  constructor() {
    super();
    this.state = {
      users: [],
      title: 'Test.io',
      isAuthenticated: false,
    };
    this.logoutUser = this.logoutUser.bind(this);
    this.loginUser = this.loginUser.bind(this);
  };
  componentWillMount() {
    if (window.localStorage.getItem('authToken')) {
      this.setState({ isAuthenticated: true });
    };
  };
  componentDidMount() {
    this.getUsers();
  };
  getUsers() {
    axios.get(`${process.env.REACT_APP_WEB_SERVICE_URL}/users`)
    .then((res) => { this.setState({ users: res.data.data.users }); })
    .catch((err) => { });
  };
  logoutUser() {
    window.localStorage.clear();
    this.setState({ isAuthenticated: false });
  };
  loginUser(token) {
    window.localStorage.setItem('authToken', token);
    this.setState({ isAuthenticated: true });
    this.getUsers();
  };
  render() {
    return (
      <div>
        <NavBar
          title={this.state.title}
          isAuthenticated={this.state.isAuthenticated}
        />
        <section className="section">
          <div className="container">
            <div className="columns">
              <div className="column is-half">
                <br/>
                <Switch>
                  <Route exact path='/' render={() => (
                    <UsersList
                      users={this.state.users}
                    />
                  )} />
                  <Route exact path='/about' component={About}/>
                  <Route exact path='/register' render={() => (
                    <Form
                      formType={'Register'}
                      isAuthenticated={this.state.isAuthenticated}
                      loginUser={this.loginUser}
                    />
                  )} />
                  <Route exact path='/login' render={() => (
                    <Form
                      formType={'Login'}
                      isAuthenticated={this.state.isAuthenticated}
                      loginUser={this.loginUser}
                    />
                  )} />
                  <Route exact path='/logout' render={() => (
                    <Logout
                      logoutUser={this.logoutUser}
                      isAuthenticated={this.state.isAuthenticated}
                    />
                  )} />
                  <Route exact path='/status' render={() => (
                    <UserStatus
                      isAuthenticated={this.state.isAuthenticated}
                    />
                  )} />
                </Switch>
              </div>
            </div>
          </div>
        </section>
      </div>
    )
  }
};

export default App;

不过,我不明白,因为上面的代码在index.js:1446 Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`. in input (at Form.jsx:72) in div (at Form.jsx:71) in form (at Form.jsx:69) in div (at Form.jsx:61) in Form (at App.jsx:66) in Route (at App.jsx:65) in Switch (at App.jsx:58) in div (at App.jsx:56) in div (at App.jsx:55) in div (at App.jsx:54) in section (at App.jsx:53) in div (at App.jsx:48) in App (at src/index.js:9) in Router (created by BrowserRouter) in BrowserRouter (at src/index.js:8) 中处理了表单更改,如下所示:

<input>

那我想念什么?表单甚至不接受输入。

2 个答案:

答案 0 :(得分:2)

您从根本上误解了React组件中的props概念。我将尝试使用您的应用程序的更简化版本进行解释。让我们以表格为例。

class Form extends Component {

  handleFormChange(){
    console.log("This is the form change function inside -Form-");
  }

  render(){
    return(
    <div>
     <input
      name="email"
      type="text"
      value={this.state.email}
      onChange={this.handleFormChange} // Focus point 1 - Calls local function
    />
     <input
      name="username"
      type="text"
      value={this.state.username}
      onChange={this.props.handleFormChange} // Focus point 2 - Calls function passed down via props
    />  
   </div>

    );
  }


}


class App extends Component {

  handleFormChange(){
      console.log("This is the form change function inside -App-");
  }

  render(){
    return <Form handleFormChange={this.handleFormChange} />
  }

}

如您所见,应用程序将呈现Form组件。看一下焦点1和2。在第一个焦点中,它试图访问本地的'handleFormChange'函数。第二个尝试调用父级通过props提供的任何函数。

所以发生的事情是,您要告诉“表单”组件访问handleFormChange函数,该函数应该由父级提供为“ prop”,即this.props.handleFormChange。因此,在安装组件时,React尝试将this.props.handleFormChange绑定到输入的onChange事件。

但是在您的实例中,未提供组件中的“ handleFormChange”道具。因此this.props.handleFormChange将不确定,从而导致该警告。

因此,要连接 表单组件内的任何处理程序,它们不应与“ this.props”链接。初始化组件时,父项应提供通过prop访问的任何处理程序。

答案 1 :(得分:1)

这是因为您没有将handleFormChange的任何道具从App.jsx传递到Form组件。

相反,它在您自己的Form组件中。

因此,只需尝试一下onChange={this.handleFormChange}