【问题标题】:How to handle multiple input fields through single component in React如何通过 React 中的单个组件处理多个输入字段
【发布时间】:2021-01-14 21:02:44
【问题描述】:

我有以下应用程序,可以选择在酒店住宿的天数。

到目前为止,我编写的代码导致以下情况:当我单击随机“+”按钮时,所有输入字段同时更改数字,这当然不是我想要实现的行为。谁能告诉我如何分别处理所有输入字段并计算所有夜晚的总价(晚数 * 每晚价格)?

酒店列表组件

import React, { useState, useEffect } from 'react';
import './HotelList.scss';
import axios from 'axios';
import Hotel from '../Hotel/Hotel';


    const HotelList = () => {
    
        const [hotel, setHotel] = useState([]);
        const [loading, setLoading] = useState(true);
        const [error, setError] = useState('');
        const [nights, setNights] = useState(0);
    
        useEffect(() => {
            const fetchData = async () => {
                await axios.get('https://60007292cb21e10017af8f04.mockapi.io/api/v1/hotels')
                .then(response => {
                    setHotel(response.data);
                    setLoading(false);
    
                })
                .catch(error => {
                    setLoading(false);
                    setError(error.message);
                })
            }
            fetchData();
        }, [])
    
    
        const addNights = () => {
            setNights(nights + 1);
        }
    
        return(
            <div>
                {!loading ? <div>
                    {hotel.map(htl => {
                        return <div key={htl.id} >
                                    <hr/>
                                        <Hotel 
                                        title={htl.hotel} 
                                        description={htl.description} 
                                        price={htl.price} 
                                        image={htl.photoURL}
                                        nights={nights}
                                        addNights={addNights}/>
                                </div>
                            })}
                            <p>Total price: </p>
                </div> : <div className="ring"><div className="lds-dual-ring"></div></div>}
                
            </div>
    
        );
    };
    
    export default HotelList;

酒店组件

import React from 'react';
import './Hotel.scss';

const Hotel = ({ title, description, price, image, nights, addNights }) => {
    return(
        <div className="container">
            <div className="img">
                <img src={image} alt="hotel" />
            </div>
            <div className="info">
                <h1>{title}</h1>
                <p>{description}</p>
            </div>
            <div className="vl"></div>
            <div className="price">
                <button>-</button>
                <input type="number" value={nights}/>
                <button onClick={addNights}>+</button>
            </div>
            <div className="inner-container">
                <i className="fas fa-trash"></i>
                <p>${price}</p>
            </div>
        </div>
    )
};

export default Hotel;

【问题讨论】:

    标签: reactjs input


    【解决方案1】:

    您需要使用唯一标识符标识每个复选框状态。 当点击时,它将根据该标识符更新状态。

    试试这个解决方案。

    HotelList 组件

    import React, { useState, useEffect } from "react";
    import "./HotelList.scss";
    import axios from "axios";
    import Hotel from "./Hotel";
    
    const HotelList = () => {
      const [hotel, setHotel] = useState([]);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState("");
      const [nights, setNights] = useState({});
    
      useEffect(() => {
        const fetchData = async () => {
          await axios
            .get("https://60007292cb21e10017af8f04.mockapi.io/api/v1/hotels")
            .then((response) => {
              setHotel(response.data);
              setLoading(false);
            })
            .catch((error) => {
              setLoading(false);
              setError(error.message);
            });
        };
        fetchData();
      }, []);
    
      const addNights = (id) => {
        let nightsCount = nights[id] || 0;
        setNights({ ...nights, [id]: nightsCount + 1 });
      };
    
      const removeNights = (id) => {
        if (nights[id] > 0) setNights({ ...nights, [id]: nights[id] - 1 });
      };
        
      return (
        <div>
          {!loading ? (
            <div>
              {hotel.map((htl) => {
                return (
                  <div key={htl.id}>
                    <hr />
                    <Hotel
                      id={htl.id}
                      title={htl.hotel}
                      description={htl.description}
                      price={htl.price}
                      image={htl.photoURL}
                      nights={nights}
                      addNights={addNights}
                      removeNights={removeNights}
                    />
                  </div>
                );
              })}
              <p>Total price: </p>
            </div>
          ) : (
            <div className="ring">
              <div className="lds-dual-ring"></div>
            </div>
          )}
        </div>
      );
    };
    
    export default HotelList;
    

    酒店组件

    import React from "react";
    import "./Hotel.scss";
    
    const Hotel = ({ id, title, description, price, image, nights, addNights, removeNights }) => {
      return (
        <div className="container">
          <div className="img">
            <img src={image} alt="hotel" />
          </div>
          <div className="info">
            <h1>{title}</h1>
            <p>{description}</p>
          </div>
          <div className="vl"></div>
          <div className="price">
            <button onClick={() => removeNights(id)}>-</button>
            <input type="number" value={nights[id]} />
            <button onClick={() => addNights(id)}>+</button>
          </div>
          <div className="inner-container">
            <i className="fas fa-trash"></i>
            <p>${price}</p>
          </div>
        </div>
      );
    };
    
    export default Hotel;
    

    live working demo

    基于类的组件

    class HotelListClass extends Component {
      state = {
        hotel: [],
        loading: true,
        error: "",
        nights: {}
      };
    
      componentDidMount() {
        this.fetchData();
      }
    
      fetchData = async () => {
        await axios
          .get("https://60007292cb21e10017af8f04.mockapi.io/api/v1/hotels")
          .then((response) => {
            this.setState({ hotel: response.data });
            this.setState({ loading: false });
          })
          .catch((error) => {
            this.setState({ loading: false });
            this.setState({ error: error.message });
          });
      };
    
      addNights = (id) => {
        const { nights } = this.state;
        let nightsCount = nights[id] || 0;
        this.setState({
          nights: { ...nights, [id]: nightsCount + 1 }
        });
      };
    
      removeNights = (id) => {
        const { nights } = this.state;
        if (nights[id] > 0) {
          this.setState({
            nights: { ...nights, [id]: nights[id] - 1 }
          });
        }
      };
    
      render() {
        const { loading, hotel, nights } = this.state;
        return (
          <div>
            {!loading ? (
              <div>
                {hotel.map((htl) => {
                  return (
                    <div key={htl.id}>
                      <hr />
                      <Hotel
                        id={htl.id}
                        title={htl.hotel}
                        description={htl.description}
                        price={htl.price}
                        image={htl.photoURL}
                        nights={nights}
                        addNights={this.addNights}
                        removeNights={this.removeNights}
                      />
                    </div>
                  );
                })}
                <p>Total price: </p>
              </div>
            ) : (
              <div className="ring">
                <div className="lds-dual-ring"></div>
              </div>
            )}
          </div>
        );
      }
    }
    
    export default HotelListClass;
    

    live code

    【讨论】:

    • 非常感谢,您有什么想法,如果我想在基于类的组件中做同样的事情,我做错了什么? addNights = (id) =&gt; { let nightsCount = this.state.nights[id] || 0; this.setState({...this.state.nights, [id]: nightsCount + 1}); }
    • 上面的代码在类组件中不起作用
    • 状态如下:state = { hotel: [], loading: true, error: '', nights: { 1: 1, 2: 1, 3: 1, 4: 1, 5: 1 }, totalPrice: null }
    • @Przemo,在上面提到的代码中,您可能忘记设置 state 属性,在您的情况下为“nights”,您的函数应该是这样的。 addNights = (id) => { let nightsCount = this.state.nights[id] || 0; this.setState({nights: {...this.state.nights, [id]: nightsCount + 1}} ); }
    • 另外,检查基于类的组件的更新代码
    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    相关资源
    最近更新 更多