javascript - React 表单无法正常工作( Prop 问题(?))

标签 javascript reactjs

我的任务是创建以下项目: Form + Report

一切都很好,但问题是没有一个组件在工作:

  • 不能填写名字和姓氏;

  • 从列表中选择无效;

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

  • 当按下“提交”按钮时 - 一切都消失了。

似乎我向功能组件传递了错误的值(?)

您能解释一下我的错误以便我改正吗?

这是我的 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) 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

关于javascript - React 表单无法正常工作( Prop 问题(?)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54003192/

相关文章:

reactjs - 是否可以使用 Graph Toolkit 2.0 在 Microsoft Teams 选项卡中进行静默身份验证

reactjs - Jest TypeError : e. preventDefault 不是函数

reactjs - 如何通过多个子组件传递事件?

JavaScript 意外行为 2 个问题(数学错误且未显示简单结果)

javascript - MochaJS setTimeout ES6

javascript - 从日期范围计算工作日

javascript - 在对象数组中查找特定键值

javascript - React 如何更新他的状态?

javascript - 删除项目后无法将其重新添加到购物篮(数组)

javascript - 在自定义 React hook 中使用 fetch - 数据获取两次