我可以从 ReactJS 的父元素中检索属性值吗?
Can I retrieve a attribute value from a parent element in ReactJS?
当我点击一个特定的按钮时,我想捕获与其关联的 {country} 属性。
我厌倦了以下
import React, { useState, useEffect } from 'react'
import axios from 'axios'
// ====================================================================[SEARCH-BAR]=======================================================
// search component
const SearchBar = (props) => {
// console.log(props);
const { searchString, searchOnChangeEventHandler } = props
return (
<>
<form>
<label>Search </label>
<input type='text' placeholder='type to search...' value={searchString} onChange={searchOnChangeEventHandler} />
</form>
</>
)
}
// ================================================================[COUNTRY_CARD]==========================================================
// countryCard component
const CountryCard = (props) => {
console.log(props);
return (
<div>
<p>countryName</p>
<p>capital</p>
<p>population</p>
<p>languages</p>
<ul>
<li>item</li>
<li>item</li>
</ul>
<p>image flag</p>
</div>
)
}
// ===================================================================[DISPLAY]===========================================================
// display component
const Display = (props) => {
const [showCountryCard, setShowCountryCard] = useState(false)
const [thisCountry, setThisCountry] = useState({})
// console.log(props);
const { countries, searchString } = props
// console.log(countries);
// eslint-disable-next-line eqeqeq
// searchString empty
if (searchString == false) {
return (
<>
<div>
<span>Type in SearchBar for a country...</span>
</div>
</>
)
}
// to count number of matches
const filteredResultsCount = countries.filter(country => country.name.toLowerCase().includes(searchString.toLowerCase())).length
// function to filterCountries
const filteredResults = (searchString, countries) => countries.filter(country => {
return country.name.toLowerCase().includes(searchString.toLowerCase())
})
// RENDER CONDITIONS
// searchString return <= 10 matches && >1 match
// event handler for show-btn
const showCardEventHandler = (event) => {
console.log(event.target.parentElement);
setShowCountryCard(!showCountryCard)
}
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{
filteredResults(searchString, countries).map(country =>
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={showCardEventHandler}
>show</button>
</li>
)
}
</ul>
{
showCountryCard ? <p>show country card</p> : null
}
</>
)
}
// searchString returns >10 matches
if (filteredResultsCount > 10) {
return (
<span>{filteredResultsCount} matches!, please refine your search...</span>
)
}
// searchString returns ===1 match
if (filteredResultsCount === 1) {
return (
<>
{
filteredResults(searchString, countries).map(country => <CountryCard key={country.numericCode} country={country} />)
}
</>
)
}
// invalid searchString
if (filteredResultsCount === 0) {
return (
<span><strong>{filteredResultsCount} matches!</strong> please refine your search...</span>
)
}
}
// ===================================================================[APP]==============================================================
// app component
const App = () => {
// to store countries
const [countries, setCountries] = useState([])
// to fetch data from
const url = 'https://restcountries.eu/rest/v2/all'
useEffect(() => {
// console.log('effect');
axios
.get(url)
.then(response => {
// console.log('promise fulfilled');
const countries = response.data
// array of objects
setCountries(countries)
})
}, [])
// console.log('countries', countries.length);
// console.log(countries);
// to store search string
const [searchString, setSearchString] = useState('')
// event handler search input
const searchOnChangeEventHandler = (event) => setSearchString(event.target.value)
return (
<>
<h1>Countries Data</h1>
<SearchBar searchString={searchString} searchOnChangeEventHandler={searchOnChangeEventHandler} />
<br />
<Display countries={countries} searchString={searchString} />
</>
)
}
export default App
请看一下 <Display/>
组件,特别是我正在努力处理这部分
const showCardEventHandler = (event) => {
console.log(event.target.parentElement);
setShowCountryCard(!showCountryCard)
}
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{
filteredResults(searchString, countries).map(country =>
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={showCardEventHandler}
>show</button>
</li>
)
}
</ul>
{
showCountryCard ? <p>show country card</p> : null
}
</>
)
}
我希望能够呈现超过 10 个国家的列表,并允许用户单击特定国家,然后将用于呈现 <CountryCard/>
组件。
如果从搜索中只有 1 个匹配值,那么我将直接显示国家卡组件。第二个功能有效。
在以下重构之后,第一个功能起作用了,但我有点困惑为什么我要添加到 post。这是正在渲染的组件,现在我正在传递 country prop onClick,就像这样
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{filteredResults(searchString, countries).map((country) => (
<li key={country.numericCode} country={country}>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={() => toggleCardEventHandler(country)}>
{showCountryCard ? 'hide' : 'show'}
</button>
</li>
))}
</ul>
{showCountryCard ? <CountryCard country={country} /> : null}
</>
);
}
事件处理如下
const toggleCardEventHandler = (country) => {
// console.log(country);
setShowCountryCard(!showCountryCard);
setCountry(country)
};
这工作正常。
我的问题是,当我更改 eventHandler onClick={toggleCardEventHandler(country)}
它会中断,但它不应该通过闭包访问吗?
另外,如果我把代码改成这样
onClick={() => {
toggleCardEventHandler()
setCountry(country)
}}
代码按我想要的方式运行,但哪种方式更好,可以将值传递给 toggleCardEventHandler()
并在那里设置国家/地区或像这样设置?
据我了解,您想将 country.name
传递给您的 showCardEventHandler。
更新 showCardEventHandler
以获取事件和国家名称:
const showCardEventHandler = (event, countryName) => {
console.log(countryName);
setShowCountryCard(!showCountryCard)
}
现在将国家名称传递给函数:
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={e => showCardEventHandler(e, country.name)}
>show</button>
</li>
由于您没有使用 showCardEventHandler
中的事件,您可以将其从签名中删除
const showCardEventHandler = (countryName) => {}
并用 onClick={() => showCardEventHandler(country.name)}
调用它
当我点击一个特定的按钮时,我想捕获与其关联的 {country} 属性。 我厌倦了以下
import React, { useState, useEffect } from 'react'
import axios from 'axios'
// ====================================================================[SEARCH-BAR]=======================================================
// search component
const SearchBar = (props) => {
// console.log(props);
const { searchString, searchOnChangeEventHandler } = props
return (
<>
<form>
<label>Search </label>
<input type='text' placeholder='type to search...' value={searchString} onChange={searchOnChangeEventHandler} />
</form>
</>
)
}
// ================================================================[COUNTRY_CARD]==========================================================
// countryCard component
const CountryCard = (props) => {
console.log(props);
return (
<div>
<p>countryName</p>
<p>capital</p>
<p>population</p>
<p>languages</p>
<ul>
<li>item</li>
<li>item</li>
</ul>
<p>image flag</p>
</div>
)
}
// ===================================================================[DISPLAY]===========================================================
// display component
const Display = (props) => {
const [showCountryCard, setShowCountryCard] = useState(false)
const [thisCountry, setThisCountry] = useState({})
// console.log(props);
const { countries, searchString } = props
// console.log(countries);
// eslint-disable-next-line eqeqeq
// searchString empty
if (searchString == false) {
return (
<>
<div>
<span>Type in SearchBar for a country...</span>
</div>
</>
)
}
// to count number of matches
const filteredResultsCount = countries.filter(country => country.name.toLowerCase().includes(searchString.toLowerCase())).length
// function to filterCountries
const filteredResults = (searchString, countries) => countries.filter(country => {
return country.name.toLowerCase().includes(searchString.toLowerCase())
})
// RENDER CONDITIONS
// searchString return <= 10 matches && >1 match
// event handler for show-btn
const showCardEventHandler = (event) => {
console.log(event.target.parentElement);
setShowCountryCard(!showCountryCard)
}
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{
filteredResults(searchString, countries).map(country =>
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={showCardEventHandler}
>show</button>
</li>
)
}
</ul>
{
showCountryCard ? <p>show country card</p> : null
}
</>
)
}
// searchString returns >10 matches
if (filteredResultsCount > 10) {
return (
<span>{filteredResultsCount} matches!, please refine your search...</span>
)
}
// searchString returns ===1 match
if (filteredResultsCount === 1) {
return (
<>
{
filteredResults(searchString, countries).map(country => <CountryCard key={country.numericCode} country={country} />)
}
</>
)
}
// invalid searchString
if (filteredResultsCount === 0) {
return (
<span><strong>{filteredResultsCount} matches!</strong> please refine your search...</span>
)
}
}
// ===================================================================[APP]==============================================================
// app component
const App = () => {
// to store countries
const [countries, setCountries] = useState([])
// to fetch data from
const url = 'https://restcountries.eu/rest/v2/all'
useEffect(() => {
// console.log('effect');
axios
.get(url)
.then(response => {
// console.log('promise fulfilled');
const countries = response.data
// array of objects
setCountries(countries)
})
}, [])
// console.log('countries', countries.length);
// console.log(countries);
// to store search string
const [searchString, setSearchString] = useState('')
// event handler search input
const searchOnChangeEventHandler = (event) => setSearchString(event.target.value)
return (
<>
<h1>Countries Data</h1>
<SearchBar searchString={searchString} searchOnChangeEventHandler={searchOnChangeEventHandler} />
<br />
<Display countries={countries} searchString={searchString} />
</>
)
}
export default App
请看一下 <Display/>
组件,特别是我正在努力处理这部分
const showCardEventHandler = (event) => {
console.log(event.target.parentElement);
setShowCountryCard(!showCountryCard)
}
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{
filteredResults(searchString, countries).map(country =>
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={showCardEventHandler}
>show</button>
</li>
)
}
</ul>
{
showCountryCard ? <p>show country card</p> : null
}
</>
)
}
我希望能够呈现超过 10 个国家的列表,并允许用户单击特定国家,然后将用于呈现 <CountryCard/>
组件。
如果从搜索中只有 1 个匹配值,那么我将直接显示国家卡组件。第二个功能有效。
在以下重构之后,第一个功能起作用了,但我有点困惑为什么我要添加到 post。这是正在渲染的组件,现在我正在传递 country prop onClick,就像这样
if (filteredResultsCount <= 10 && filteredResultsCount > 1) {
return (
<>
<ul>
{filteredResults(searchString, countries).map((country) => (
<li key={country.numericCode} country={country}>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={() => toggleCardEventHandler(country)}>
{showCountryCard ? 'hide' : 'show'}
</button>
</li>
))}
</ul>
{showCountryCard ? <CountryCard country={country} /> : null}
</>
);
}
事件处理如下
const toggleCardEventHandler = (country) => {
// console.log(country);
setShowCountryCard(!showCountryCard);
setCountry(country)
};
这工作正常。
我的问题是,当我更改 eventHandler onClick={toggleCardEventHandler(country)}
它会中断,但它不应该通过闭包访问吗?
另外,如果我把代码改成这样
onClick={() => {
toggleCardEventHandler()
setCountry(country)
}}
代码按我想要的方式运行,但哪种方式更好,可以将值传递给 toggleCardEventHandler()
并在那里设置国家/地区或像这样设置?
据我了解,您想将 country.name
传递给您的 showCardEventHandler。
更新 showCardEventHandler
以获取事件和国家名称:
const showCardEventHandler = (event, countryName) => {
console.log(countryName);
setShowCountryCard(!showCountryCard)
}
现在将国家名称传递给函数:
<li
key={country.numericCode}
country={country}
>
<span>{country.name}</span>
<button
value={showCountryCard}
onClick={e => showCardEventHandler(e, country.name)}
>show</button>
</li>
由于您没有使用 showCardEventHandler
中的事件,您可以将其从签名中删除
const showCardEventHandler = (countryName) => {}
并用 onClick={() => showCardEventHandler(country.name)}