如何在反应中以多步形式将图像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>
谁能告诉我如何纠正我的错误?
正如我从您的代码中看到的,您试图从不存在的对象中获取 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>
)
}
}
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>
谁能告诉我如何纠正我的错误?
正如我从您的代码中看到的,您试图从不存在的对象中获取 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>
)
}
}