React表单无法正常工作(道具问题(?))

时间:2019-01-02 08:20:07

标签: javascript reactjs

我有一个任务来创建以下项目: Form + Report

一切都很好,但是问题在于所有组件都没有起作用:

  • 无法填写名字和姓氏;

  • 从列表中选择无效;

  • 无法检查清单中的任何选项;

  • 按“提交”按钮时-所有内容均消失。

似乎我正在将错误的值传递给功能组件(?)

您能向我解释我的错误,以便我纠正它们吗?

这里是指向我的CodePen

的链接

整个代码:

    // Lists of activities and restrictions
    const optionsList = ['Science Lab','Swimming','Cooking','Painting'];
    const checkList = [{id: 'a', text:'Dietary Restrictions'},
                       {id: 'b', text:'Physical Disabilities'},
                       {id: 'b', text:'Medical Needs'}]
    // First Name and LastName component
    function NameInput(props){
      return (
        <div>
          <label>{props.label}</label>
          <br/>
          <input type ='text' value={props.value} onChange={props.handleChange} />
        </div>
      )
    }
    // List of activities component
    function SelectList(props){
      return (
        <div>
          <label>{props.label}</label>
          <br/>
          <select value={props.value} onChange={props.handleChange}>
            {props.optionsList.map( (item, index) =>
                <option key={index} value = {item}> {item} </option>)}
          </select>  
        </div>
      )
    }
    // CheckBox list component
    function CheckBox(props){
       return (
         <p>
           <label>{props.value}) {props.label}</label>
           <input type="checkbox" name={props.name} id={props.id} value={props.value} checked={props.checked} onChange={props.handleChange} />
         </p>
       )
    }
    // CheckbBoxList component
    function CheckBoxList(props){
      return (
        <div>
          <label>{props.title}</label>
          <ol>
            {props.checkList.map((item,index) =>
              <CheckBox 
                key = {index}
                id = {props.id+'_'+index}
                name = {props.id}
                value = {item.id}
                checked = {(props.applyList.indexOf(item.id) < 0 ? false : true)}
                label = {item.text}
                handleChange = {props.handleChange}
               />)
             }
          </ol>
        </div>
      )
    }
    // Remove button component
    function RemoveButton(props){
      return (
        <button onClick= {() => props.handleClick()}>x</button>
      )
    }
    // Report element
    function ReportElem(props){
      return (
        <tbody>
        {props.reportElem.map((item, index) => 
          <tr key={index}>
            <td><RemoveButton /></td>
            <td>{item.firstName}</td> 
            <td>{item.lastName}</td>
            <td>{item.activity}</td>
            <td>{item.apply}</td> 
          </tr>
        )}
        </tbody>
      )
    }
    // Report table
    function ReportTable(props){
      return (
        <table>
          <thead>
            <tr>
              <th>Remove</th>
              <th>First Name</th>
              <th>Last Name</th>
              <th>Activity</th>
              <th>Restrictions</th>
            </tr>
          </thead>
          <ReportElem reportList = {props.reportList} />
        </table>
      )
    }

    class App extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          firstName: '',
          lastName: '',
          activity: this.props.optionsList[0],
          apply: [],
          items: []
        }
      }
      // Handle multiple inputs
      handleChange(event){
        this.setState({[event.target.name]: event.target.value})
      }
      // Handle CheckList changes
      handleChangeChk(event){
        let itemsCopy = this.state.apply
        if (event.target.chacked){
          itemsCopy.push(event.target.value)
        } else {
          console.log(itemsCopy.indexOf(event.target.value))
          itemsCopy.splice(itemsCopy.indexOf(event.target.value), 1)
        }
        this.setState({apply: itemsCopy})
      }
      // Add new item to the report and refresh the initial state
      addItem(){
        let itemsCopy = this.state.items
        itemsCopy.push({
          firstName: this.state.firstName,
          lastName: this.state.lastName,
          activity: this.state.activity,
          apply: this.state.apply.join(',')
        })
        this.setState({
          firstName: '', 
          lastName: '',
          activity: this.props.optionsList[0],
          apply: [],
          items: itemsCopy
        })
      }


      render(){
        return (
          <div>
            <NameInput label = 'First Name' value = {this.state.firstName} handleChange = {this.handleChange.bind(this)} />
            <NameInput label = 'Last Name' value = {this.state.lastName} handleChange = {this.handleChange.bind(this)} />
            <SelectList label = 'Select Activity' optionsList={this.props.optionsList} value = {this.state.activity} handleChange = {this.handleChange.bind(this)} />
            <CheckBoxList title = {'Check all that apply'} checkList={this.props.checkList} applyList = {this.state.apply} handleChange = {this.handleChangeChk.bind(this)} />
            <button className = 'submit' onClick = {() => this.addItem()}>Submit</button>
            {this.state.items.length > 0 && <ReportTable reportList = {this.state.items} />}
          </div>
        )
      }
    }

    ReactDOM.render(
   <App optionsList={optionsList} checkList={checkList}/>, document.getElementById('root')
)

1 个答案:

答案 0 :(得分:1)

您需要在这里照顾一些事情

1)this.setState({[event.target.name]: event.target.value})在这里,您期望的是target.name,但是您的输入没有名称,因此没有状态被更新

2)您需要将名称传递给组件

<NameInput label = 'First Name' value = {this.state.firstName} name="firstName" handleChange = {this.handleChange.bind(this)} />

以及您的组件中

 <input type ='text' name={props.name} value={props.value} onChange={props.handleChange} />

因此,通过这种方式,您可以拥有要从州传递的名称

3)您的检查清单包含相同的ID

[{id: 'a', text:'Dietary Restrictions'},
                   {id: 'b', text:'Physical Disabilities'},
                   {id: 'b', text:'Medical Needs'}]

将其更改为

const checkList = [{id: 'a', text:'Dietary Restrictions'},
                   {id: 'b', text:'Physical Disabilities'},
                   {id: 'c', text:'Medical Needs'}]

4)在报告元素中,您需要拥有props.reportList而不是props.reportElem

一旦您应用了此更改,您的代码就会像这样

// Lists of activities and restrictions
const optionsList = ['Science Lab','Swimming','Cooking','Painting'];
const checkList = [{id: 'a', text:'Dietary Restrictions'},
                   {id: 'b', text:'Physical Disabilities'},
                   {id: 'c', text:'Medical Needs'}]
// First Name and LastName component
function NameInput(props){
  return (
    <div>
      <label>{props.label}</label>
      <br/>
      <input type ='text' name={props.name} value={props.value} onChange={props.handleChange} />
    </div>
  )
}
// List of activities componnt
function SelectList(props) {
  return (
    <div>
      <label>{props.label}</label>
      <br/>
      <select name={props.name} value={props.value} onChange={props.handleChange}>
        {props.optionsList.map( (item, index) =>
            <option key={index} value = {item}> {item} </option>)}
      </select>  
    </div>
  )
}
// CheckBox list component
function CheckBox(props){
   return (
     <p>
       <label>{props.value}) {props.label}</label>
       <input type="checkbox" name={props.name} id={props.id} value={props.value} checked={props.checked} onChange={props.handleChange} />
     </p>
   )
}
// CheckbBoxList component
function CheckBoxList(props){
  return (
    <div>
      <label>{props.title}</label>
      <ol>
        {props.checkList.map((item,index) =>
          <CheckBox 
            key = {index}
            id = {props.id+'_'+index}
            name = {props.id}
            value = {item.id}
            checked = {(props.applyList.indexOf(item.id) < 0 ? false : true)}
            label = {item.text}
            handleChange = {props.handleChange}
           />)
         }
      </ol>
    </div>
  )
}
// Remove button component
function RemoveButton(props){
  return (
    <button onClick= {() => props.handleClick()}>x</button>
  )
}
// Report element
function ReportElem(props){
  debugger;
  return (
    <tbody>
    {props.reportList.map((item, index) => 
      <tr key={index}>
        <td><RemoveButton /></td>
        <td>{item.firstName}</td> 
        <td>{item.lastName}</td>
        <td>{item.activity}</td>
        <td>{item.apply}</td> 
      </tr>
    )}
    </tbody>
  )
}
// Report table
function ReportTable(props){
  return (
    <table>
      <thead>
        <tr>
          <th>Remove</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Activity</th>
          <th>Restrictions</th>
        </tr>
      </thead>
      <ReportElem reportList = {props.reportList} />
    </table>
  )
}

class App extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      firstName: '',
      lastName: '',
      activity: this.props.optionsList[0],
      apply: [],
      items: []
    }
  }
  // Handle multiple inputs
  handleChange(event){   
    this.setState({[event.target.name]: event.target.value})
  }
  // Handle CheckList changes
  handleChangeChk(event){
    let itemsCopy = this.state.apply
    if (event.target.checked){
      itemsCopy.push(event.target.value)
    } else {
      console.log(itemsCopy.indexOf(event.target.value))
      itemsCopy.splice(itemsCopy.indexOf(event.target.value), 1)
    }
    this.setState({apply: itemsCopy})
  }
  // Add new item to the report and refresh the initial state
  addItem(){
    debugger;
    let itemsCopy = JSON.parse(JSON.stringify(this.state.items)) 
    itemsCopy.push({
      firstName: this.state.firstName,
      lastName: this.state.lastName,
      activity: this.state.activity,
      apply: this.state.apply.join(',')
    })
    this.setState({
      firstName: '', 
      lastName: '',
      activity: this.props.optionsList[0],
      apply: [],
      items: itemsCopy
    })
  }


  render(){
    console.log(this.state);
    return (
      <div>
        <NameInput label = 'First Name' value = {this.state.firstName} name="firstName" handleChange = {this.handleChange.bind(this)} />
        <NameInput label = 'Last Name' value = {this.state.lastName} name="lastName" handleChange = {this.handleChange.bind(this)} />
        <SelectList label = 'Select Activity' name="activity" optionsList={this.props.optionsList} value = {this.state.activity} handleChange = {this.handleChange.bind(this)} />
        <CheckBoxList title = {'Check all that apply'} name="apply" checkList={this.props.checkList} applyList = {this.state.apply} handleChange = {this.handleChangeChk.bind(this)} />
        <button className = 'submit' onClick = {() => this.addItem()}>Submit</button>
        {this.state.items.length > 0 && <ReportTable reportList = {this.state.items} />}
      </div>
    )
  }
}

ReactDOM.render(
   <App optionsList={optionsList} checkList={checkList}/>,
    document.getElementById('root')
)

Demo