如何在反应中以多步形式将图像src添加到状态

How to add image src to the state in multi step form in react

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

我想做的实际上是在 Multiform.js 组件中同步和保存 <Select/><img> 的数据,就像我们在步进器表单中看到的那样。

但是,正如 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.

正如我从您的代码中看到的,您试图从不存在的对象中获取 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 属性,当你 select 一个国家时,将其设置为 Multiform,最后通过道具将其传递给 StepOne。

简答

您遇到错误是因为 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