映射和传递 onClick 函数作为道具后如何定位特定元素
Posted
技术标签:
【中文标题】映射和传递 onClick 函数作为道具后如何定位特定元素【英文标题】:How to target specific element after mapping and passing onClick function as props 【发布时间】:2019-10-02 22:59:12 【问题描述】:我正面临这样的问题,我从 API 获取记录数组,将其映射为单个元素并将它们作为单个组件输出。我有改变父组件状态的功能,将值传递给子组件,子组件应该在单击按钮后隐藏/显示 div 内容。
当然。它正在工作,但部分 - 我的所有 div 都被隐藏/显示。我为每个子组件设置了特定的键,但它不起作用。
App.js
import React, Component from 'react';
import './App.css';
import axios from 'axios';
import countries from '../../countriesList';
import CitySearchForm from './CitySearchForm/CitySearchForm';
import CityOutput from './CityOutput/CityOutput';
import ErrorMessage from './ErrorMessage/ErrorMessage';
class App extends Component
state =
country: '',
error: false,
cities: [],
infoMessage: '',
visible: false
getCities = (e) =>
e.preventDefault();
const countryName = e.target.elements.country.value.charAt(0).toUpperCase() + e.target.elements.country.value.slice(1);
const countryUrl = 'https://api.openaq.org/v1/countries';
const wikiUrl ='https://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&explaintext&format=json&category=city&redirects&origin=*&titles=';
const allowedCountries = new RegExp(/spain|germany|poland|france/, 'i');
if (allowedCountries.test(countryName))
axios
.get(countryUrl)
.then( response =>
const country = response.data.results.find(el => el.name === countryName);
return axios.get(`https://api.openaq.org/v1/cities?country=$country.code&order_by=count&sort=desc&limit=10`)
)
.then( response =>
const cities = response.data.results.map(record =>
return name: record.city ;
);
cities.forEach(city =>
axios
.get(wikiUrl + city.name)
.then( response =>
let id;
for (let key in response.data.query.pages)
id = key;
const description = response.data.query.pages[id].extract;
this.setState(prevState => (
cities: [...prevState.cities, city: `$city.name`, description],
infoMessage: prevState.infoMessage = ''
))
)
)
)
.catch(error =>
console.log('oopsie, something went wrong', error)
)
else
this.setState(prevState => (
infoMessage: prevState.infoMessage = 'This is demo version of our application and is working only for Spain, Poland, Germany and France',
cities: [...prevState.cities = []]
))
descriptionTogglerHandler = () =>
this.setState((prevState) =>
return visible: !prevState.visible;
);
;
render ()
return (
<div className="App">
<ErrorMessage error=this.state.infoMessage/>
<div className="form-wrapper">
<CitySearchForm getCities=this.getCities getInformation=this.getInformation countries=countries/>
</div>
this.state.cities.map(( city, description ) => (
<CityOutput
key=city
city=city
description=description
show=this.state.visible
descriptionToggler=this.descriptionTogglerHandler />
))
</div>
);
export default App;
CityOutput.js
import React, Component from 'react';
import './CityOutput.css';
class CityOutput extends Component
render()
const city, descriptionToggler, description, show = this.props;
let descriptionClasses = 'output-record description'
if (show)
descriptionClasses = 'output-record description open';
return (
<div className="output">
<div className="output-record"><b>City:</b> city</div>
<button onClick=descriptionToggler>Read more</button>
<div className=descriptionClasses>description</div>
</div>
)
;
export default CityOutput;
【问题讨论】:
常见错误——一个数组的值 【参考方案1】:将visible
键和切换功能放在CityOutput
中,而不是放在父级中
import React, Component from "react";
import "./CityOutput.css";
class CityOutput extends Component
state =
visible: true
;
descriptionTogglerHandler = () =>
this.setState( visible: !this.state.visible );
;
render()
const city, description = this.props;
let descriptionClasses = "output-record description";
if (this.state.visible)
descriptionClasses = "output-record description open";
return (
<div className="output">
<div className="output-record">
<b>City:</b> city
</div>
<button onClick=() => this.descriptionTogglerHandler()>Read more</button>
<div className=descriptionClasses>description</div>
</div>
);
export default CityOutput;
【讨论】:
在你的例子中onClick=() => this.descriptionToggler()
不应该是 onClick=this. descriptionTogglerHandler
吗?看起来你有不同的函数名称
@Ted 我在使用onClick=this.descriptionTogglerHandler
时遇到了问题,因为函数descriptionTogglerHandler
被立即调用,但没有针对这个特定示例进行测试
这不应该是一个问题 - 但我的意思更多的是名称不匹配的问题:descriptionTogglerHandler
vs this.descriptionToggler
【参考方案2】:
有两种方法可以解决这个问题,
第一个是在您的状态中设置一个键属性,并检查该键并将其与子键进行比较,例如:
state =
country: '',
error: false,
cities: [],
infoMessage: '',
visible: false.
currKey: 0
descriptionTogglerHandler = (key) =>
this.setState((prevState) =>
return currKey: key, visible: !prevState.visible;
);
;
// then in your child component
class CityOutput extends Component
render()
const city, descriptionToggler, description, show, currKey, elKey = this.props;
let descriptionClasses = 'output-record description'
if (show && elKey === currKey)
descriptionClasses = 'output-record description open';
return (
<div className="output">
<div className="output-record"><b>City:</b> city</div>
<button onClick=() => descriptionToggler(elKey)>Read more</button>
<div className=descriptionClasses>description</div>
</div>
)
;
另一种方式是为每个子组件设置一个隔离状态
class CityOutput extends Component
constructor(props)
this.state =
show: false
function descriptionToggler()
const show = this.state;
this.setState(
show: !show
)
render()
const city, descriptionToggler, description = this.props;
let descriptionClasses = 'output-record description'
if (this.state.show)
descriptionClasses = 'output-record description open';
return (
<div className="output">
<div className="output-record"><b>City:</b> city</div>
<button onClick=descriptionToggler>Read more</button>
<div className=descriptionClasses>description</div>
</div>
)
;
我希望这会有所帮助;)
【讨论】:
我非常感谢这个答案,因为它涵盖了 2 个场景以上是关于映射和传递 onClick 函数作为道具后如何定位特定元素的主要内容,如果未能解决你的问题,请参考以下文章