【问题标题】:How to add image src to the state in multi step form in react如何在反应中以多步形式将图像src添加到状态
【发布时间】:2020-08-26 20:33:20
【问题描述】:

TLDR

我正在为我的项目制作一个多步骤表单,其灵感来自Brad Traversy's Tutorial of making Multi-Step form in React。 所以按照这个表格的基本结构
我制作了一个名为Multiform 的主要父组件,如下所示

import React, { Component } from 'react'
import StepOne from './StepOne'
export class Multiform extends Component {
    state = {
    step:1,
    CountryFlag: 'https://raw.githubusercontent.com/MeRahulAhire/country-calling-code-html/master/phone_icon.png',
    CountryCode: ''
};
handleChange = (input) => (e) => {
    this.setState({ [input]: e.target.value });
};

countryFlagHandler = () =>{
    this.setState({CountryFlag : this.props.state.flagImg})
  }
render() {
    const { CountryFlag, CountryCode } = this.state;
    const values = {CountryFlag, CountryCode };

    switch (step) {
        case 1:
          return(
            <StepOne
            handleChange={this.handleChange}
            countryFlagHandler={this.countryFlagHandler}
            values={values}
            />

          )
         default:
             return (<h1>hello React App</h1>)

    };
}
}

export default Multiform

还有一个子组件StepOne如下

import React, { Component } from 'react'
    export class StepOne extends Component {
        
        state = {
    flagImg: '',
};
render() {
    const { values, handleChange, countryFlagHandler } = this.props;

    const selectCountryChange = () => {
        const img = document.querySelector('#img');
        const select = document.querySelector('#country');
        img.src = `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`;

        this.setState({
            flagImg: `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`
        });
        countryFlagHandler()
    };
    return (
        <div>
            <div class="image" onChange={selectCountryChange}>  
                <img src={values.CountryFlag} id="img"/>  
            </div>
            <select id="country" onChange={handleChange('select')} defaultValue={values.select}>  
                <option data-countryCode="IN" value="91">India</option>  
                <option data-countryCode="US" value="1">US</option>  
                <option data-countryCode="GB" value="44">UK</option>  
            </select> 
        </div>
    )
}
    }
    
    export default StepOne

我要做的实际上是将&lt;Select/&gt;&lt;img&gt; 的数据同步并保留在Multiform.js 组件中,就像我们在步进表单中看到的那样。

但是,就像StepOne

<img src={values.CountryFlag} id="img"/>

img.src 实际上是由函数selectCountryChange 操作的,为了保持img.src 的值不变,我想在Multiform 中创建countryFlagHandler 并将其导入StepOne

但是当我选择任何值时,它给了我这个错误:

TypeError:无法读取未定义的属性“flagImg”

Registration.countryFlagHandler
C:/Users/Rahul/Desktop/cfm-usersignup/src/public/form/registration.js:53
  50 |   this.setState({ [input]: e.target.value });
  51 | };
  52 | countryFlagHandler = () =>{
> 53 |   this.setState({CountryFlag : this.props.state.flagImg})
     | ^  54 | }
  55 | 
  56 |

&

selectCountryChange
C:/Users/Rahul/Desktop/cfm-usersignup/src/public/form/credential.js:31
  28 |  this.setState({
  29 |      flagImg: `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`
  30 |  });
> 31 |  countryFlagHandler();
     | ^  32 | };
  33 | return (
  34 |  <div>

谁能告诉我如何纠正我的错误?

You can also checkout my project repo for more info.

【问题讨论】:

    标签: reactjs default-value react-props setstate react-state-management


    【解决方案1】:

    简短回答

    您收到错误是因为countryFlagHandler 没有获得预期的值,它无权访问StepOne 组件的状态。您需要将该值作为参数传递给父组件。

      // flagImg will come as an argument from the child Component
       countryFlagHandler = (flagImg) =>{
          this.setState({ CountryFlag : flagImg })
       }
    
        const selectCountryChange = () => {
        const img = document.querySelector('#img');
        const select = document.querySelector('#country');
        img.src = `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`;
    
        this.setState({
            flagImg: `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`
        });
        const countryFlag = `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`;
        // CountryFlag would be passed as an argument
        countryFlagHandler(countryFlag);
       };
    

    长答案

    我建议稍微重构您的代码并将所有数据移动到父组件,而不是将它们保持在两种不同的状态。而且一个函数就足以处理所有的数据操作。

    父组件Multiform

    import React, { Component } from 'react'
    import StepOne from './StepOne'
    export class Multiform extends Component {
    state = {
        step: 1,
        CountryFlag: 'https://raw.githubusercontent.com/MeRahulAhire/country-calling-code-html/master/phone_icon.png',
        CountryCode: ''
    };
    
    handleSelectChange = (event) => {
        const value = event.target.value;
        const countryCode = event.target[event.target.selectedIndex].getAttribute('data-country-code');
        const countryFlagImg = `https://flagpedia.net/data/flags/h80/${countryCode.toLowerCase()}.webp`;
    
        this.setState({
            select: value,
            CountryFlag: countryFlagImg
        });
    }
    
    render() {
        const { CountryFlag, CountryCode, step } = this.state;
        const values = { CountryFlag, CountryCode };
    
        switch (step) {
            case 1:
                return (
                    <StepOne
                        handleChange={this.handleSelectChange}
                        countryFlagHandler={this.countryFlagHandler}
                        values={values}
                    />
    
                )
            default:
                return (<h1>hello React App</h1>)
    
        };
      }
    }
    

    子组件StepOne

    import React, { Component } from 'react'
    class StepOne extends Component {
    render() {
        const { values, handleChange } = this.props;
    
        return (
            <div>
                <div class="image">
                    <img src={values.CountryFlag} id="img" />
                </div>
    
                <select id="country" onChange={this.props.handleChange} defaultValue={values.select}>
                    <option data-country-code="IN" value="91">India</option>
                    <option data-country-code="US" value="1">US</option>
                    <option data-country-code="GB" value="44">UK</option>
                </select>
            </div>
        )
      }
    }
    

    Running Example

    【讨论】:

      【解决方案2】:

      正如我从您的代码中看到的,您尝试从不存在的对象中获取 flagImg 属性。如果我正确理解了您的逻辑,您需要更新 selectCountryChange 和 countryFlagHandler 方法:

      const selectCountryChange = () => {
          const img = document.querySelector('#img');
          const select = document.querySelector('#country');
          const flagImg = `https://flagpedia.net/data/flags/h80/${select.selectedOptions[0].dataset.countrycode.toLowerCase()}.webp`;
          img.src = flagImg;
      
          this.setState({
              flagImg
          });
          countryFlagHandler(flagImg)
      };
      

      并在 countryFlagHandler 方法中从 argumnets 中获取:

      countryFlagHandler = CountryFlag =>
          this.setState({ CountryFlag })
      

      另外,您的逻辑看起来很脏,也许您可​​以生成 flagImg 属性,当您选择一个国家时,将其设置为 Multiform,最后通过 props 将其传递给 StepOne。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-26
        • 2020-10-15
        • 1970-01-01
        • 2018-09-14
        • 2011-10-01
        • 1970-01-01
        相关资源
        最近更新 更多