【问题标题】:React input form without form component?反应没有表单组件的输入表单?
【发布时间】:2019-11-08 20:43:49
【问题描述】:

我正在编写一个“Todo”应用程序来学习 React,这是我的第一个应用程序(它使用 Rails 作为后端)。目前我有两个处理状态的组件,这是我遇到问题的地方。

ListContainer 保存“Lists”的状态,而“List”保存单个 ListItems 的状态。现在列表工作得很好,但是我想为我的“列表”组件添加一个简单的输入框,它可以快速将一个新的列表项添加到列表中。目前我可以添加一个“测试”值就好了。

一种方法是制作一个 ListItemForm 组件,但这似乎没有必要只发送一个值。我更像是一个后端人员,所以我确信有一种简单的方法并不明显。我的 javascript 也很生锈,所以我确定它充满了错误。

这里是List 组件:

import React, { Component } from 'react';
import axios from 'axios';
import ListItem from './ListItem';


class List extends Component { 
    constructor(props){
        super(props)
        this.state = {
            listItems: []
        }
    }

    componentDidMount() {
        axios.get(`/api/v1/lists/${this.props.list.id}/list_items.json`)
        .then(response => {
            console.log("Getting List 'listitems'")
            console.log(response.data)
            console.log(this.state.listItems)
            this.setState({
                listItems: response.data
            })
            console.log(this.state)
        })
        .catch(error => console.log(error))
    }

    addNewListItem = (list_id, content) => {
        axios.post(`/api/v1/lists/${list_id}/list_items`, {
            content: content
          })
        .then(response => {
            console.log(response)
            const listItems = [ ...this.state.listItems, response.data ]
            this.setState({listItems})
            console.log("state of list")
            console.log(this.state)

        })
        .catch(error => {
            console.log(error)
        })
    }

    removeListItem = (listItem_id) => {
        console.log("listItem_id :" + listItem_id);
        axios.delete(`/api/v1/list_items/${listItem_id}`)
        .then(response => {
            console.log(response);
            const listItems = this.state.listItems.filter(
                listItem => listItem.id !== listItem_id
            )
            this.setState({listItems})

        })
        .catch(error => {
            console.log(error)
        })
    }

    render() {
        return (
            <div className="single-list" key={this.props.list.id}>
                <h4>{this.props.list.title}</h4>
                <p>{this.props.list.description}</p>
                {console.log(this.props.list)}
                {this.state.listItems.map( listItem => {
                    return <ListItem key={listItem.id} listItem={listItem} removeListItem={this.removeListItem}/>
                })}
                <button onClick={() => this.props.onRemoveList(this.props.list.id)}>Erase</button>
                <button onClick={() => this.props.onUpdateList(this.props.list.id)}>Update</button>
                <button onClick={() => this.addNewListItem(this.props.list.id,"test")}>Add</button>
            </div>
        )
    }
}

export default List;

我希望该字段位于底部,并且只是一个带有按钮的文本字段。还是像输入并附加提交按钮和onClick 处理程序以将e.target.value 发送到addNewListItem 函数一样简单?还是我想多了?

希望在“List”组件而不是“ListItem”中包含输入表单是有意义的

【问题讨论】:

  • 是的,就像添加一个&lt;input&gt;,附加一个onInput 一样简单。
  • @JonasWilms 是对的,但我不希望在用户完成输入任何他们正在输入的内容并按下按钮之前触发该功能。从我阅读onInput 的内容来看,每次文本更改时都会触发?
  • 除非您将表单数据提交到服务器,否则您不需要&lt;form&gt;。如果您希望“在按下按钮时”发生事情,请将您的事件侦听器添加到该按钮。但在捕获用户输入时,remember how React works 也很重要:您仍然需要让 onChange 处理该输入以实际获取用户输入的值,并将其存储在您的状态中。然后,您的按钮的 onClick 可以对该状态值做任何需要做的事情;它应该尝试访问输入元素的 DOM 节点或其他东西。
  • 是的。每当输入发生变化时,将其存储在状态中。然后当按钮被点击时,从该状态创建一个新项目,并重置输入
  • @Mike'Pomax'Kamermans 问题是 List 组件中的状态是存储 ListItems 数组。所以它需要我为此创造一个新的状态......我想这不是世界末日,只是我试图避免的事情。我现在意识到,虽然我忘记了如果没有状态更改,react 不会更新……所以我想创建一个新状态是有意义的。

标签: javascript reactjs


【解决方案1】:

您必须将输入的值放在组件的状态中,并且当您调用添加按钮时,传递输入的状态。

import React, { Component } from 'react';
import axios from 'axios';
import ListItem from './ListItem';


class List extends Component { 
    constructor(props){
        super(props)
        this.state = {
            listItems: [],
            newItem: ''
        }

        this.handleChange = this.handleChange.bind(this);
    }

    componentDidMount() {
        axios.get(`/api/v1/lists/${this.props.list.id}/list_items.json`)
        .then(response => {
            console.log("Getting List 'listitems'")
            console.log(response.data)
            console.log(this.state.listItems)
            this.setState({
                listItems: response.data
            })
            console.log(this.state)
        })
        .catch(error => console.log(error))
    }

    addNewListItem = (list_id, content) => {
        axios.post(`/api/v1/lists/${list_id}/list_items`, {
            content: content
          })
        .then(response => {
            console.log(response)
            const listItems = [ ...this.state.listItems, response.data ]
            this.setState({listItems})
            console.log("state of list")
            console.log(this.state)

            this.setState({
              newItem: ''
            });
        })
        .catch(error => {
            console.log(error)
        })
    }

    removeListItem = (listItem_id) => {
        console.log("listItem_id :" + listItem_id);
        axios.delete(`/api/v1/list_items/${listItem_id}`)
        .then(response => {
            console.log(response);
            const listItems = this.state.listItems.filter(
                listItem => listItem.id !== listItem_id
            )
            this.setState({listItems})

        })
        .catch(error => {
            console.log(error)
        })
    }

    handleChange (event) {
      this.setState({ newItem: event.target.value });
    }

    render() {
        return (
            <div className="single-list" key={this.props.list.id}>
                <h4>{this.props.list.title}</h4>
                <p>{this.props.list.description}</p>
                {console.log(this.props.list)}
                {this.state.listItems.map( listItem => {
                    return <ListItem key={listItem.id} listItem={listItem} removeListItem={this.removeListItem}/>
                })}
                <button onClick={() => this.props.onRemoveList(this.props.list.id)}>Erase</button>
                <button onClick={() => this.props.onUpdateList(this.props.list.id)}>Update</button>

                <input value={this.state.newItem} onChange={this.handleChange}/>
                <button onClick={() => this.addNewListItem(this.props.list.id, this.state.newItem)}>Add</button>
            </div>
        )
    }
}

export default List;

【讨论】:

  • 附带问题:为什么我注意到的反应事件处理程序似乎从不使用 es6 箭头?这不会避免绑定它们的需要吗?还有提交后清除输入字段值的好方法吗?
  • @msmith1114 由于输入的值被置于组件的状态中,因此当您的 API 以 200(OK)响应时,必须在真空中修改状态。箭头函数用于保存需要执行的函数,避免放置this.handleChange = this.handleChange.bind(this);可以尝试调用输入的方法onChange={this.handleChange.bind(this)}。这将消除将方法定义放在组件的构造函数中的需要
猜你喜欢
  • 2020-12-30
  • 1970-01-01
  • 2018-09-21
  • 2021-09-29
  • 2016-08-17
  • 1970-01-01
  • 2021-01-12
  • 2020-02-03
  • 1970-01-01
相关资源
最近更新 更多