简体   繁体   English

如何将具有切换 function 的 state 组件转换为 reactjs 中的无状态组件?

[英]How can I convert a state component that has a toggle function to a stateless one in reactjs?

I am trying to convert the following component to a functional one so I could use the react context API?我正在尝试将以下组件转换为功能组件,以便可以使用反应上下文 API?

The JSX code for the component I want to convert我要转换的组件的 JSX 代码

class pizzaModal extends Component {
  state = {
    selected: "small",
    showModal: true,
    selectedOrder: null
  }
  toggleHandler = (size)=> ()=>{
    this.setState({
            toggle: size
        });
  }
  addToOrders = (p)=>{
    this.setState(prevState=>({
      selectedOrder: p
    }))
  }
  
  render (){
    let attachedClasses = [styles.ImageContainer]
    if(this.state.toggle==='small'){
      attachedClasses = [styles.ImageContainer, styles.Small]
    }
    if(this.state.toggle==="medium"){
      attachedClasses = [styles.ImageContainer, styles.Medium]
    }
    if(this.state.toggle==="large"){
      attachedClasses=[styles.ImageContainer, styles.Large]
    }
    return (
      <Aux>
        <div className={styles.Pizzamodal}>
          <div className={styles.ModalContainer}>
            <div className={attachedClasses.join(' ')}>
              <img  src={this.props.image} alt="pizzapicture"/>
            </div>
            <div className={styles.DetailsContainer}>
              <div>
                <div className={styles.TextDetails}>
                  <h1>{this.props.name}</h1>
                  <p>{this.props.ingredients}</p>
                </div>
                <div>
                <div className={styles.Form}>
                <form className={styles.switchButton}>
                  <input type="radio" name="pizza" id="small" value="small" onChange={this.toggleHandler("small")}
                            checked={this.state.toggle==="small"}/>
                  <label for="small">Small</label>
                  <input type="radio" name="pizza" id="medium" value="medium" onChange={this.toggleHandler("medium")}
                            checked={this.state.toggle==="medium"}/>
                  <label for="medium">Medium</label>
                  <input type="radio" name="pizza" id="large" value="large" onChange={this.toggleHandler("large")}
                            checked={this.state.toggle==="large"}/>
                  <label for="large">Large</label>
                </form>
                </div>
                <div className={styles.orderButton}>
                  <button onClick={this.props.addToOrders}>Add to basket for ₦{this.props.price}</button>
                </div>
              </div>
              </div>
            </div>  
            <div className={styles.Navbar} onClick={this.props.clicked}>
            <div></div>
            <div></div>
          </div>
          </div>
         
      </div>
      </Aux>
    )
  }
}
export default pizzaModal;

This is what I have done这就是我所做的

const PizzaModal= (props) => {
  const [Selected, setSelected] = useState('small')
  
  const toggleHandler = (size)=>{
    setSelected({
            toggle: Selected
        });
  }
  /*const [orders, setOrders] = useContext([CartContext]);
  const addToOrders=()=>{
    const pizza = {name: this.props.name, ingredients: this.props.ingredients, image: this.props.image, price: this.props.price}
      setOrders([...orders, pizza])
  
  }*/
  
    let attachedClasses = [styles.ImageContainer]
    if(setSelected(Selected==='small')){
      attachedClasses = [styles.ImageContainer, styles.Small]
    }
    if(setSelected(Selected==="medium")){
      attachedClasses = [styles.ImageContainer, styles.Medium]
    }
    if(setSelected(Selected==="large")){
      attachedClasses=[styles.ImageContainer, styles.Large]
    }
    return (
      <Aux>
        <div className={styles.Pizzamodal}>
          <div className={styles.ModalContainer}>
            <div className={attachedClasses.join(' ')}>
              <img  src={props.image} alt="pizzapicture"/>
            </div>
            <div className={styles.DetailsContainer}>
              <div>
                <div className={styles.TextDetails}>
                  <h1>{props.name}</h1>
                  <p>{props.ingredients}</p>
                </div>
                <div>
                <div className={styles.Form}>
                <form className={styles.switchButton}>
                  <input type="radio" name="pizza" id="small" value="small" onChange={toggleHandler("small")}
                            checked={setSelected(Selected==='small')}/>
                  <label for="small">Small</label>
                  <input type="radio" name="pizza" id="medium" value="medium" onChange={toggleHandler("medium")}
                            checked={setSelected(Selected==='medium')}/>
                  <label for="medium">Medium</label>
                  <input type="radio" name="pizza" id="large" value="large" onChange={toggleHandler("large")}
                            checked={setSelected(Selected==='large')}/>
                  <label for="large">Large</label>
                </form>
                </div>
                <div className={styles.orderButton}>
                  <button >Add to basket for ₦{props.price}</button>
                </div>
              </div>
              </div>
            </div>  
            <div className={styles.Navbar} onClick={props.clicked}>
            <div></div>
            <div></div>
          </div>
          </div>
         
      </div>
      </Aux>
    )
  
}
export default PizzaModal;

I have no error messages on my IDE or on the webpage but when I click on the button that toggles the modal on I get a blank white screen with no error messages.我的 IDE 或网页上没有错误消息,但是当我单击切换模式的按钮时,我得到一个没有错误消息的空白屏幕。

couple of mistakes i spotted in your code see if this changes anything我在您的代码中发现了几个错误,看看这是否会改变任何东西

  1. You dont need a seperate toggleHandler function to change value of Selected that is what setSelected is there for.您不需要单独的 toggleHandler function 来更改 Selected 的值,这就是 setSelected 的用途。
  2. You gave setSelected an object你给了 setSelected 一个 object
setSelected({toggle: Selected});

instead u should give it the value of Selected相反,你应该给它 Selected 的值

setSelected(Selected);
  1. And in all the if statements在所有的 if 语句中
if(setSelected(Selected==='small'))

is wrong u just have to check错了你只需要检查

if(Selected==='small')

4.And finally in OnChange 4.最后在 OnChange

onChange={toggleHandler("small")}

you can just call setSelected你可以调用 setSelected

onChange={() => setSelected("small")}

The useState hook returns the current value of the state variable and a function to change it. useState挂钩返回 state 变量的当前值和 function 以更改它。 In your case with在你的情况下

const [selected, setSelected] = useState('small')

you would use selected anywhere you previously would have used this.state.selected and use setSelected() anywhere you previously would have used this.setState({ selected }) .您可以在以前使用过this.state.selected的任何地方使用selected ,并在以前使用过this.setState({ selected })的任何地方使用setSelected() ) 。 So the first issue in your code is the misuse of the setter function when reading the state value.因此,代码中的第一个问题是在读取 state 值时滥用设置器 function。

When you want to pass a function to a component, you have to make sure you're passing the function and not a call to the function.当您想将 function 传递给组件时,您必须确保传递的是 function 而不是对 function 的调用。 For example例如

onChange={toggleHandler("large")}

will immediately get the return value of toggleHandler("large") and try to call that when the value changes.立即获得toggleHandler("large")的返回值,并在值更改时尝试调用它。 Your definition of toggleHandler doesn't return anything, so when you change your radio buttons, you're actually just trying to call undefined as a function, which of course doesn't work.您对toggleHandler的定义没有返回任何内容,因此当您更改单选按钮时,您实际上只是试图将undefined调用为 function,这当然不起作用。

Also, the onChange handler of an input passes a synthetic event.此外,输入的onChange处理程序传递一个合成事件。 You should use that to extract which radio button was pressed.您应该使用它来提取按下了哪个单选按钮。

Try something like this:尝试这样的事情:

const PizzaModal = (props) => {
    const [selected, setSelected] = useState('small')
    
    const toggleHandler = (event) => {
      setSelected(event.target.value);
    }
  
    let attachedClasses = [styles.ImageContainer]
    if (selected === 'small')) {
      attachedClasses = [styles.ImageContainer, styles.Small]
    }
    if (selected === "medium")) {
      attachedClasses = [styles.ImageContainer, styles.Medium]
    }
    if (selected === "large")) {
      attachedClasses=[styles.ImageContainer, styles.Large]
    }
    return (
      <Aux>
        <div className={styles.Pizzamodal}>
          <div className={styles.ModalContainer}>
            <div className={attachedClasses.join(' ')}>
              <img  src={props.image} alt="pizzapicture"/>
            </div>
            <div className={styles.DetailsContainer}>
              <div>
                <div className={styles.TextDetails}>
                  <h1>{props.name}</h1>
                  <p>{props.ingredients}</p>
                </div>
                <div>
                <div className={styles.Form}>
                <form className={styles.switchButton}>
                  <input type="radio" name="pizza" id="small" value="small" onChange={toggleHandler} checked={selected === 'small'}/>
                  <label for="small">Small</label>
                  <input type="radio" name="pizza" id="medium" value="medium" onChange={toggleHandler} checked={selected === 'medium'}/>
                  <label for="medium">Medium</label>
                  <input type="radio" name="pizza" id="large" value="large" onChange={toggleHandler} checked={selected === 'large'}/>
                  <label for="large">Large</label>
                </form>
                </div>
                <div className={styles.orderButton}>
                  <button >Add to basket for ₦{props.price}</button>
                </div>
              </div>
              </div>
            </div>  
            <div className={styles.Navbar} onClick={props.clicked}>
            <div></div>
            <div></div>
          </div>
          </div>
         
      </div>
      </Aux>
    )
  
}
export default PizzaModal;

For future reference, errors also come through in the browser's Javascript console (usually in the developer tools section).为了将来参考,浏览器的 Javascript 控制台(通常在开发人员工具部分)中也会出现错误。 You can check there for errors.你可以在那里检查错误。 My guess is that some combination of trying to call undefined as a function and a render loop due to the setSelected calls is what was causing your issue.我的猜测是,由于setSelected调用而尝试将undefined调用为 function 和渲染循环的某种组合是导致您的问题的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在reactjs中调用无状态功能组件内部的函数 - How can I call a function inside of stateless functional component in reactjs 如何在本机反应中将无状态 function 转换为 class 组件 - How can I convert stateless function to class component in react native 如何通过在无状态组件中的开关内调用函数来更新父状态? - How can I update the parent state by calling a function within a switch in my stateless component ? 使用无状态函数定义组件时如何初始化状态 - How can I Initialize the state when using a stateless function to define my component 如何将 jquery 转换为 reactjs 组件? - how can I convert jquery to reactjs component? ReactJS:我可以在一个单独的组件中分离一个改变状态的函数吗? - ReactJS: Can I separate a function that changes state in a separate component? 将此函数转换为无状态的React组件 - Convert this function to a stateless react component 如何在 ReactJS 的功能组件中管理 4 Checkbox 的状态? - How I can manage the state for 4 Checkbox in functional component in ReactJS? 在React上,如何在功能/无状态组件上调用组件安装上的函数? - On React, how can I call a function on component mount on a functional/stateless component? 如何在条件中另一个组件下方的无状态组件上呈现函数? - How can I render a function on a stateless component just below another component within a conditional?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM