使用反应和打字稿仅切换地图数组的一个元素
Toggle only one element of map array with react and typescript
我正在映射评论 API 的数组,我想在点击“阅读更多”时只显示点击的评论,但目前正在扩展我的数组的所有评论,我我正在使用打字稿,这对我来说是全新的,所以我不知道如何移动,我应该如何将索引信息传递给我的状态?
interface State {
reviews: Review[];
isReadMore: boolean;
}
export default class MoviePage extends Component<{}, State> {
state: State = {
reviews: [],
isReadMore: false,
};
componentDidMount() {
this.asyncAwaitFunc();
this.toggle(arguments);
}
asyncAwaitFunc = async () => {
try {
const reviewmovie = await axios.get<ReviewResponse>(
`https://api.themoviedb.org/3/movie/${this.props.match.params.id}/reviews?api_key=`
);
this.setState({
reviews: reviewmovie.data.results,
});
} catch (error) {}
};
toggle(index: any) {
this.setState({
isReadMore: !this.state.isReadMore,
});
render() {
const { isReadMore, reviews } = this.state;
return (
<>
<ReviewGrid>
{reviews.map((review, index) => (
<ReviewContent key={index}>
{this.state.isReadMore
? review.content.substring(0, 650)
: review.content}
<Button onClick={() => this.toggle(index)}>
{isReadMore ? "...read more" : " show less"}
</Button>
</ReviewContent>
))}
</ReviewGrid>
</>
);
}
}
由于我无权访问 API 或您正在使用的各种界面和组件,因此我对您的代码进行了一些修改以使其正常工作,但这应该能让您有所了解。您将 isReadMore
作为单个状态进行跟踪,这就是它对数组中的每个项目进行切换的原因。您需要为每个评论单独跟踪状态。这是可行的几种解决方案之一,但这里的想法是采用 API 的响应,并将其映射到一组新的对象,其中包括您将添加的新键 isReadMore
,那么您可以为每条评论单独切换 属性。
Here 是 CodeSandbox 上的工作示例。
编辑: Here is a link 到第二个示例,它不需要您映射 api 调用的结果以添加新密钥跟踪 isReadMore
状态。此方法改为在 Map<Review, boolean>
中单独跟踪状态。 ES6 地图在这里工作得很好,因为您可以使用评论对象本身作为键,布尔值可以跟踪您的 hide/show 状态。
原解
interface Review {
title: string;
content: string;
}
interface MyReview extends Review {
isReadMore: boolean;
}
interface State {
reviews: MyReview[];
}
export default class MoviePage extends React.Component<{}, State> {
state: State = {
reviews: []
};
componentDidMount() {
this.asyncAwaitFunc();
}
asyncAwaitFunc = () => {
try {
const reviewsFromApi: Review[] = [
{
title: "Some Movie",
content: "some movie review that's pretty long"
},
{
title: "Some Other Movie",
content: "an even longer super long movie review that's super long"
}
];
this.setState({
reviews: reviewsFromApi.map((r) => ({ ...r, isReadMore: false }))
});
} catch (error) {
console.log(error);
}
};
toggle(index: number) {
this.setState({
reviews: this.state.reviews.map((r, i) => {
if (i === index) {
return {
...r,
isReadMore: !r.isReadMore
};
}
return r;
})
});
}
render() {
const { reviews } = this.state;
return (
<>
<div>
{reviews.map((review, index) => (
<div key={index}>
<p>
{review.isReadMore
? review.content.substring(0, 10) + "..."
: review.content}
</p>
<button onClick={() => this.toggle(index)}>
{review.isReadMore ? "Read more" : " Show less"}
</button>
</div>
))}
</div>
</>
);
}
}
我认为问题在于您保存了一次 isReadMore,但您需要为每次评论保存 isReadMore。
这是一个例子:
interface ReviewRow {
review: Review
isReadMore: boolean
}
interface State {
reviews: ReviewRow[]
}
export default class MoviePage extends Component<{}, State> {
state: State = {
reviews: []
}
componentDidMount() {
this.asyncAwaitFunc()
}
asyncAwaitFunc = async () => {
try {
const reviewMovies = await axios.get<ReviewResponse>(
`https://api.themoviedb.org/3/movie/${this.props.match.params.id}/reviews?api_key=`
)
this.setState({
reviews: reviewMovies.data.results.map((review) => {
return { review: review, isReadMore: false }
})
})
} catch (error) {
console.log(error)
}
}
toggle(index: number) {
const { reviews } = this.state
reviews[index].isReadMore = !reviews[index].isReadMore
this.setState({ reviews })
}
render() {
const { reviews } = this.state
return (
<>
<ReviewGrid>
{reviews.map((reviewRow, index) => {
;<ReviewContent key={index}>
{ reviewRow.isReadMore ? reviewRow.review.content.substring(0, 650) : reviewRow.review..content}
<Button onClick={() => this.toggle(index)}>{reviewRow.isReadMore ? '...read more' : ' show less'}</Button>
</ReviewContent>
})}
</ReviewGrid>
</>
)
}
}
我正在映射评论 API 的数组,我想在点击“阅读更多”时只显示点击的评论,但目前正在扩展我的数组的所有评论,我我正在使用打字稿,这对我来说是全新的,所以我不知道如何移动,我应该如何将索引信息传递给我的状态?
interface State {
reviews: Review[];
isReadMore: boolean;
}
export default class MoviePage extends Component<{}, State> {
state: State = {
reviews: [],
isReadMore: false,
};
componentDidMount() {
this.asyncAwaitFunc();
this.toggle(arguments);
}
asyncAwaitFunc = async () => {
try {
const reviewmovie = await axios.get<ReviewResponse>(
`https://api.themoviedb.org/3/movie/${this.props.match.params.id}/reviews?api_key=`
);
this.setState({
reviews: reviewmovie.data.results,
});
} catch (error) {}
};
toggle(index: any) {
this.setState({
isReadMore: !this.state.isReadMore,
});
render() {
const { isReadMore, reviews } = this.state;
return (
<>
<ReviewGrid>
{reviews.map((review, index) => (
<ReviewContent key={index}>
{this.state.isReadMore
? review.content.substring(0, 650)
: review.content}
<Button onClick={() => this.toggle(index)}>
{isReadMore ? "...read more" : " show less"}
</Button>
</ReviewContent>
))}
</ReviewGrid>
</>
);
}
}
由于我无权访问 API 或您正在使用的各种界面和组件,因此我对您的代码进行了一些修改以使其正常工作,但这应该能让您有所了解。您将 isReadMore
作为单个状态进行跟踪,这就是它对数组中的每个项目进行切换的原因。您需要为每个评论单独跟踪状态。这是可行的几种解决方案之一,但这里的想法是采用 API 的响应,并将其映射到一组新的对象,其中包括您将添加的新键 isReadMore
,那么您可以为每条评论单独切换 属性。
Here 是 CodeSandbox 上的工作示例。
编辑: Here is a link 到第二个示例,它不需要您映射 api 调用的结果以添加新密钥跟踪 isReadMore
状态。此方法改为在 Map<Review, boolean>
中单独跟踪状态。 ES6 地图在这里工作得很好,因为您可以使用评论对象本身作为键,布尔值可以跟踪您的 hide/show 状态。
原解
interface Review {
title: string;
content: string;
}
interface MyReview extends Review {
isReadMore: boolean;
}
interface State {
reviews: MyReview[];
}
export default class MoviePage extends React.Component<{}, State> {
state: State = {
reviews: []
};
componentDidMount() {
this.asyncAwaitFunc();
}
asyncAwaitFunc = () => {
try {
const reviewsFromApi: Review[] = [
{
title: "Some Movie",
content: "some movie review that's pretty long"
},
{
title: "Some Other Movie",
content: "an even longer super long movie review that's super long"
}
];
this.setState({
reviews: reviewsFromApi.map((r) => ({ ...r, isReadMore: false }))
});
} catch (error) {
console.log(error);
}
};
toggle(index: number) {
this.setState({
reviews: this.state.reviews.map((r, i) => {
if (i === index) {
return {
...r,
isReadMore: !r.isReadMore
};
}
return r;
})
});
}
render() {
const { reviews } = this.state;
return (
<>
<div>
{reviews.map((review, index) => (
<div key={index}>
<p>
{review.isReadMore
? review.content.substring(0, 10) + "..."
: review.content}
</p>
<button onClick={() => this.toggle(index)}>
{review.isReadMore ? "Read more" : " Show less"}
</button>
</div>
))}
</div>
</>
);
}
}
我认为问题在于您保存了一次 isReadMore,但您需要为每次评论保存 isReadMore。 这是一个例子:
interface ReviewRow {
review: Review
isReadMore: boolean
}
interface State {
reviews: ReviewRow[]
}
export default class MoviePage extends Component<{}, State> {
state: State = {
reviews: []
}
componentDidMount() {
this.asyncAwaitFunc()
}
asyncAwaitFunc = async () => {
try {
const reviewMovies = await axios.get<ReviewResponse>(
`https://api.themoviedb.org/3/movie/${this.props.match.params.id}/reviews?api_key=`
)
this.setState({
reviews: reviewMovies.data.results.map((review) => {
return { review: review, isReadMore: false }
})
})
} catch (error) {
console.log(error)
}
}
toggle(index: number) {
const { reviews } = this.state
reviews[index].isReadMore = !reviews[index].isReadMore
this.setState({ reviews })
}
render() {
const { reviews } = this.state
return (
<>
<ReviewGrid>
{reviews.map((reviewRow, index) => {
;<ReviewContent key={index}>
{ reviewRow.isReadMore ? reviewRow.review.content.substring(0, 650) : reviewRow.review..content}
<Button onClick={() => this.toggle(index)}>{reviewRow.isReadMore ? '...read more' : ' show less'}</Button>
</ReviewContent>
})}
</ReviewGrid>
</>
)
}
}