根据this个问题的反馈。我正在尝试将此WrappedApp
类组件转换为功能组件。
这是现有的(有效的)类组件:
class WrappedApp extends Component {
constructor(props) {
super(props);
this.state = {
filterText: "",
favourites: [],
};
}
// update filterText in state when user types
filterUpdate(value) {
this.setState({
filterText: value,
});
}
// add clicked name ID to the favourites array
addFavourite(id) {
const newSet = this.state.favourites.concat([id]);
this.setState({
favourites: newSet,
});
}
// remove ID from the favourites array
deleteFavourite(id) {
const { favourites } = this.state;
const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];
this.setState({
favourites: newList,
});
}
render() {
const hasSearch = this.state.filterText.length > 0;
return (
<div>
<header>
<Greeting />
<Search
filterVal={this.state.filterText}
filterUpdate={this.filterUpdate.bind(this)}
/>
</header>
<main>
<ShortList
data={this.props.data}
favourites={this.state.favourites}
deleteFavourite={this.deleteFavourite.bind(this)}
/>
<TagsList
data={this.props.data}
filter={this.state.filterText}
favourites={this.state.favourites}
addFavourite={this.addFavourite.bind(this)}
/>
{/*
Show only if user has typed in search.
To reset the input field, we pass an
empty value to the filterUpdate method
*/}
{hasSearch && (
<button onClick={this.filterUpdate.bind(this, "")}>
Clear Search
</button>
)}
</main>
</div>
);
}
}
export default WrappedApp;
此代码在WrappedApp
组件和新功能组件中使用/引用:
const Tag = ({ id, info, handleFavourite }) => (
<li className={info.count} onClick={() => handleFavourite(id)}>
{info.label} ({info.tag_related_counts_aggregate.aggregate.count})
</li>
);
const ShortList = ({ favourites, data, deleteFavourite }) => {
const hasFavourites = favourites.length > 0;
const favList = favourites.map((fav, i) => {
return (
<Tag
id={i}
key={i}
info={data.find((tag) => tag.id === fav)}
handleFavourite={(id) => deleteFavourite(id)}
/>
);
});
return (
<div className="favourites">
<h4>
{hasFavourites
? "Shortlist. Click to remove.."
: "Click on a tag to shortlist it.."}
</h4>
<ul>{favList}</ul>
{hasFavourites && <hr />}
</div>
);
};
const TagsList = ({ data, filter, favourites, addFavourite }) => {
const input = filter;
// Gather list of tags
const tags = data
// filtering out the tags that...
.filter((tag, i) => {
return (
// ...are already favourited
favourites.indexOf(tag.id) === -1 &&
// ...are not matching the current search value
!tag.label.indexOf(input)
);
})
// ...output a <Name /> component for each name
.map((tag, i) => {
// only display tags that match current input string
return (
<Tag
id={tag.id}
key={i}
info={tag}
handleFavourite={(id) => addFavourite(id)}
/>
);
});
/* ##### the component's output ##### */
return <ul>{tags}</ul>;
};
// need a component class here
// since we are using `refs`
class Search extends Component {
render() {
const { filterVal, filterUpdate } = this.props;
return (
<form>
<input
type="text"
ref="filterInput"
placeholder="Type to filter.."
// binding the input value to state
value={filterVal}
onChange={() => {
filterUpdate(this.refs.filterInput.value);
}}
/>
</form>
);
}
}
这是我最初尝试将WrappedApp
类组件转换为功能组件:
function WrappedApp(props) {
const [filterText, setfilterText] = useState("");
const [favourites, setFavourites] = useState([]);
// update filterText in state when user types
const filterUpdate = (value) => {
setfilterText(value);
};
// add clicked name ID to the favourites array
const addFavourite = (id) => {
const newSet = favourites.concat([id]);
setFavourites(favourites);
};
// remove ID from the favourites array
const deleteFavourite = (id) => {
const newList = [...favourites.slice(0, id), ...favourites.slice(id + 1)];
setFavourites(newList);
};
const hasSearch = filterText.length > 0;
return (
<div>
<header>
<Greeting />
<Search filterVal filterUpdate />
</header>
<main>
<ShortList data={props.data} favourites deleteFavourite />
<TagsList
data={props.data}
filter={filterText}
favourites
addFavourite
/>
{/*
Show only if user has typed in search.
To reset the input field, we pass an
empty value to the filterUpdate method
*/}
{hasSearch && <button onClick={filterUpdate}>Clear Search</button>}
</main>
</div>
);
}
export default WrappedApp;
我看到什么错误?
我遇到的最初问题是TypeError: favourites.map is not a function
错误消息。
答案 0 :(得分:3)
在评论中出现错误之后,
代替此:
<ShortList data={props.data} favourites deleteFavourite />
使用此:
<ShortList data={props.data}
favourites={favourities}
deleteFavourite={deleteFavourite} />
仅应用favourites
意味着它等于true
,而不是处于您所处状态的数组。
答案 1 :(得分:1)
传递道具时,您需要明确指定道具。子组件
<ShortList data={props.data} favourites={favourites} deleteFavourite={deleteFavourite} />
类似于标签列表
<TagsList
data={props.data}
filter={filterText}
favourites={favourites}
addFavourite={addFavourite}
/>