我有父组件,它有一个div,其中包含一个带有自定义组件的ol。 这些组件中的每一个都有一个状态,我在其中存储一个"已检查"的布尔值。我需要父组件中的一个按钮,该按钮将清除所有子组件状态并将其设置为 false。我正在尝试使用"useRef"和"useImperativeHandle",但无法弄清楚。
国家/地区列表(子组件(
export default function CountryListing({ country }, ref) {
const countryRef = useRef();
const [checkbox, toggleCheckbox] = useState(false)
const clearCheckbox = () => {
toggleCheckbox(false);
}
useImperativeHandle(ref, () => ({
clear: () => {ref.current.clearCheckbox()}
}
));
return (
<li key={country} >
<div className="country-listing-container">
<input type="checkbox" className="country-checkbox" id={country + "Checkbox"} ref={countryRef} value={checkbox} onChange={() => toggleCheckbox(!checkbox)}></input>
<img src={'https://storage.googleapis.com/flags-bucket/flags/' + getImageFor(country)} className="country-flag" alt={country + "'s flag icon."}></img>
<p className="country-name"> {country} </p>
</div>
</li>
);
}
可折叠(父组件(
export default function Collapsible() {
const [open, togglePanel] = useState(false);
const [countries] = useState(["Mexico", "Brazil", "United Kingdom", "Not Provided - Canada", "United States", "Russia", "Australia", "Peru", "China", "Taiwan", "Pakistan", "Yemen", "Thailand", "New Zealand", "Czech Republic", "Spain", "Japan", "South Korea", "South Africa", "Argentina", "Afghanistan", "Angola", "Andorra", "Armenia", "Fiji", "Finland", "Estonia", "Ecuador", "Egypt", "Hungary", "Iran", "Ireland", "Austria", "Poland", "Kuwait", "Libya", "Monaco", "Mongolia", "Mozambique", "Nepal", "Italy", "Norway", "Barbados", "Bolivia", "Bulgaria", "Chile", "Colombia"]);
const [searchTerm, setSearchTerm] = useState('');
const [searchResults, setSearchResults] = useState(countries);
//TODO title is not showing completely
const [title] = "Locations";
const ref = useRef(false);
const countryComponents = (countries) => {
const countriesList = countries.map(thisCountry => <CountryListing country={thisCountry} ref={ref} />);
return countriesList;
}
const [countryComponentsList, modifyCountryComponentsList] = useState(countryComponents(searchResults))
const clearAllAction = () => {
ref.current.clearCheckbox();
}
const Initials = (countries) => {
const [countryInitials] = useState(getInitials(countries.countries));
const listInitials = countryInitials.map((initial) => <li key={initial}> {initial} </li>);
return (
<ul style={{ listStyleType: "none" }}>{listInitials}</ul>
)
}
const search = (term) => {
console.log('searchTerm is ' + searchTerm);
if (!term) {
setSearchResults(countries);
}
else {
const results = countries.filter(country => country.toLowerCase().includes(term));
setSearchResults(results);
}
}
return (
<>
<div className="top-header">
<input type="text" placeholder="Filter Locations" value={searchTerm}
onKeyUp={(event) => {
setSearchTerm(event.target.value);
search(searchTerm);
}}
onChange={(event) => {
setSearchTerm(event.target.value);
search(searchTerm);
}}
onLoad={(event) => {
setSearchTerm(event.target.value);
search(searchTerm);
}}
>
</input>
<button onClick={() => search(searchTerm)}> S </button>
</div>
<div>
<div onClick={() => togglePanel(!open)} className="header">
{title}
</div>
{
open ? (
<>
<div className="before-content"><button id="clearAllButton" onClick={clearAllAction()} > X Clear All </button></div>
<div className="content">
<div className="basic-grid">
<div className="card">
<ol style={{ listStyleType: "none" }}>
{countryComponentsList}
</ol>
</div>
<div className="card">
<Initials countries={countries} />
</div>
</div>
</div>
</>
) : null
}
</div >
</>
);
}
我尝试寻找答案,但没有什么能帮助我理解它,他们通常会提到单个组件。虽然我的理解是我需要为一个组件实现它,然后映射它们。
我对你尝试的方式不太熟悉,但我可以提出一个替代方案。与其这样做,不如执行以下操作:
const [checkedElements, setCheckedElements] = useState([]);
然后,当您映射和创建元素时,您可以使用 map 方法的索引来表示类似
onClick={()=>setCheckedElements([...checkedElements, index])}
checked={checkedElements.includes(index)}
您可以通过在按钮上添加以下内容来清除单击按钮时的所有元素:
onClick={setCheckedElements([])}
这是一个完整的工作示例,您可以检查父级的所有标签:
const Parent = () => {
const [todos, setTodos] = React.useState([
{ id: 1, label: "Wake up", completed: true },
{ id: 2, label: "Make Coffee", completed: false },
{ id: 3, label: "Go to Work", completed: false }
]);
const checkAll = React.useMemo(() => {
const filterTodos = Object.assign([], todos);
return (
filterTodos.filter(f => f.completed === true).length === todos.length
);
}, [todos]);
const checkAllTodos = e => {
const value = e.target.checked;
setTodos(current => current.map(f => ({ ...f, completed: value })));
};
const checkTodo = React.useCallback(id => {
setTodos(current =>
current.map(item => {
if (item.id === id) return { ...item, completed: !item.completed };
else return item;
})
);
}, []);
return (
<div>
<ul>
<li>
<input type="checkbox" checked={checkAll} onChange={checkAllTodos} />
todos {checkAll}
</li>
{todos.map(item => (
<Todo
id={item.id}
checked={item.completed}
key={item.id}
change={checkTodo}
>
{item.label}
</Todo>
))}
</ul>
</div>
);
};
const Todo = React.memo(({ checked, children, id, change }) => (
<li>
<input type="checkbox" checked={checked} onChange={() => change(id)} />
{children}
</li>
));
ReactDOM.render(<Parent/>,document.getElementById("root"))
<script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
<div id="root"></div>