React Failed prop type:没有onChange处理程序的值

问题描述 投票:0回答:2

这是我的form组件:

Form.jsx

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组件:

App.jsx

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>正在处理表单更改,如下所示:

onChange={this.props.handleFormChange}

所以我错过了什么?表格甚至不接受投入。

javascript reactjs axios
2个回答
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} />
  }

}

如您所见,App将呈现Form组件。看看焦点1和2.在第一个焦点点,它试图访问本地的'handleFormChange'函数。而第二个试图通过道具调用父母提供的任何功能。

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

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

因此,为了连接Form组件中的任何处理程序,它们不应与'this.props'链接。在初始化组件时,父级应提供通过props访问的任何处理程序。


1
投票

因为你没有将任何名为handleFormChange的道具从App.jsx传递给Form组件。

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

所以,试试这个onChange={this.handleFormChange}

© www.soinside.com 2019 - 2024. All rights reserved.