简体   繁体   English

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

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

TLDR TLDR

I'm making an multiStep form for my project that is inspired from Brad Traversy's Tutorial of making Multi-Step form in React .我正在为我的项目制作一个多步骤表单,其灵感来自Brad Traversy 的在 React 中制作多步骤表单的教程 So as per the basic structure of this form所以按照这个表格的基本结构在此处输入图像描述
I made a main Parent component called Multiform as below我制作了一个名为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

and a child component StepOne as below和一个子组件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

what I'm trying to do is actually to sync and persist the data of <Select/> and <img> in Multiform.js Component as typically what we see in a stepper form.我要做的实际上是在Multiform.js组件中同步和持久化<Select/><img>的数据,就像我们在步进表单中看到的那样。

But, As in the StepOne但是,就像在StepOne中一样

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

the img.src is actually manipulated by the function selectCountryChange and to keep the value of img.src persisted I thought of creating countryFlagHandler in Multiform and importing it to StepOne img.src实际上由 function selectCountryChange操作并保持img.src的值保持不变我想在Multiform中创建countryFlagHandler并将其导入StepOne

but when i selected any value, it gave me this error:但是当我选择任何值时,它给了我这个错误:

TypeError: Cannot read property 'flagImg' of undefined 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>

Can anyone please tell me how to rectify my error?谁能告诉我如何纠正我的错误?

You can also checkout my project repo for more info. 您还可以查看我的项目存储库以获取更多信息。

As I see from your code, you try to get the flagImg propery from object that doesn't exist.正如我从您的代码中看到的,您尝试从不存在的 object 获取 flagImg 属性。 If I understood your logic correctly, you need to update the selectCountryChange and countryFlagHandler methods:如果我正确理解了您的逻辑,则需要更新 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)
};

and in the countryFlagHandler method take it from argumnets:并在 countryFlagHandler 方法中从 argumnets 中获取:

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

Also, your logic looks pretty dirty, maybe you could generate the flagImg property, when you select a country, set it to Multiform, and finally pass it through props to StepOne.另外,您的逻辑看起来很脏,也许您可以生成 flagImg 属性,当您 select 一个国家/地区时,将其设置为 Multiform,最后通过道具将其传递给 StepOne。

Shor answer简短的回答

You're getting an error because countryFlagHandler is not getting the value it's expected, it doesn't have access to the StepOne component's state.您收到错误是因为countryFlagHandler没有获得预期的值,它无权访问StepOne组件的 state。 You would need to pass the value as an argument to the parent component.您需要将该值作为参数传递给父组件。

  // 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);
   };

Long Answer长答案

I would recommend refactoring your code a bit and moving all the data to the parent component rather than keeping them in two different states.我建议稍微重构您的代码并将所有数据移动到父组件,而不是将它们保持在两种不同的状态。 And also one function would be enough to handle all the data manipulation.还有一个 function 足以处理所有数据操作。

Parent Component Multiform父组件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>)

    };
  }
}

And child Component StepOne和子组件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 运行示例

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM