我有一个父组件,它的div包含一个带有自定义组件的ol。 这些组件中的每一个都有一个状态,其中存储了“已检查”布尔值。我需要在父组件中有一个按钮,该按钮将清除所有子组件状态并将其设置为false。我正在尝试使用'useRef'和'useImperativeHandle',但无法弄清楚。
CountryListing(子组件)
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 >
</>
);
}
我尝试搜索答案,但是没有任何帮助我理解它,他们通常提到单个组件。尽管我的理解是我需要为一个组件实现它,然后将它们映射。
答案 0 :(得分:1)
我对您尝试的方式并不真正了解,但是我可以建议另一种选择。除了这样做,您可以执行以下操作:
const [checkedElements, setCheckedElements] = useState([]);
然后,当您映射和创建元素时,可以使用map方法的索引来表达类似的内容
onClick={()=>setCheckedElements([...checkedElements, index])}
checked={checkedElements.includes(index)}
单击按钮时,可以通过将其添加到按钮上来清除所有元素:
onClick={setCheckedElements([])}
答案 1 :(得分:0)
这是一个完整的示例,您可以检查父级的所有标签:
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>