我在更改列表中只有一个元素的样式时遇到问题。 下面是我的Main
类,以及StationDetails
类,这是我创建的用于逐个呈现列表元素的组件。
StationDetails
中有一行(第 31 行(,我似乎无法弄清楚问题所在。我想根据元素的 ID 是否包含在activeStations
列表中来设置组件的样式。
这是一行:
style={activeStations.includes(stations.id) ? pressedStyle : buttonStyle}
这是我Main
课
import React, { Component } from "react"
import axios from "axios"
import { Text, View, ScrollView } from "react-native"
import StationDetails from "./StationDetails"
class Main extends Component {
constructor(props) {
super(props)
this.state = { stations: [], pressStatus: false, activeStations: [] }
this.handleClick = this.handleClick.bind(this)
}
componentWillMount() {
axios
.get("https://api.citybik.es/v2/networks/trondheim-bysykkel")
.then(response =>
this.setState({ stations: response.data.network.stations })
)
}
handleClick() {
this.setState({ pressStatus: !this.state.pressStatus })
}
renderStations() {
return this.state.stations.map(stations => (
<StationDetails
activeStations={this.state.activeStations}
handleClick={this.handleClick}
pressStatus={this.state.pressStatus}
key={stations.id}
stations={stations}
>
{stations.name}
</StationDetails>
))
}
render() {
return (
<ScrollView style={{ flex: 1, marginTop: 20 }}>
{this.renderStations()}
</ScrollView>
)
}
}
export default Main
这是我StationDetails
组件。
import React from "react"
import { Text, View } from "react-native"
import Card from "./felles/Card"
import CardSection from "./felles/CardSection"
import Button from "./felles/Button"
const StationDetails = ({
stations,
handleClick,
pressStatus,
activeStations
}) => {
const {
headerTextStyle,
leftPartStyle,
rightPartStyle,
pressedStyle,
buttonStyle
} = styles
return (
<Card style={{ flex: 1, flexDirection: "row" }}>
<CardSection style={leftPartStyle}>
<Text style={headerTextStyle}>
{stations.name}
</Text>
<Text>
Free bikes: {stations.free_bikes}
</Text>
</CardSection>
<CardSection style={rightPartStyle}>
<Button
onPress={() => {
if (!activeStations.includes(stations.id)) {
activeStations.push(stations.id)
} else {
activeStations.splice(activeStations.indexOf(stations.id), 1)
}
}}
style={
activeStations.includes(stations.id) ? pressedStyle : buttonStyle
}
>
Abonner
</Button>
</CardSection>
</Card>
)
}
const styles = {
textStyle: {
fontSize: 14
},
leftPartStyle: {
flex: 3,
flexDirection: "column",
justifyContent: "space-between"
},
rightPartStyle: {
flex: 1
},
pressedStyle: {
backgroundColor: "green"
},
headerTextStyle: {
fontSize: 18
},
thumbnailStyle: {
height: 50,
width: 50
},
buttonStyle: {
backgroundColor: "#fff"
}
}
export default StationDetails
您正在尝试从StationDetails
设置Main.activeStations
状态,这是不可取的。要记住的几件事
- Main 的
activeStations
处于其本地组件级别状态。 - 您不应该尝试从子组件中改变它。
- 由于您将突变的
activeStations
状态分配给StationDetails
Main.activeStations
,因此ReactNative(RN(在其协调过程中没有发现状态的差异,因此不会重新渲染StationDetails
。 - 我们需要 RN 重新渲染
StationDetails
以便它为按钮等显示正确的样式。 - 有关设置状态的文档
这就是我会怎么做的
- 让
Main
渲染StationDetails
- 从
StationDetails
选择哪个电台获取回拨 - 让
Main
负责改变它自己的内部状态(activeStations
(
通过这样做,
StationDetails
只负责渲染给定道具的站点列表,而不负责渲染其他任何内容。它是一个呈现列表的愚蠢组件。Main
负责处理自己的内部状态
结果如下:
Main.js
类
import React, { Component } from 'react';
import axios from 'axios';
import { ScrollView } from 'react-native';
import StationDetails from './StationDetails';
export default class App extends Component {
constructor(props) {
super(props);
this.onSelectStation = this.onSelectStation.bind(this);
this.state = {
stations: [],
pressStatus: false,
activeStations: []
};
}
componentWillMount() {
axios.get('https://api.citybik.es/v2/networks/trondheim-bysykkel')
.then(response => this.setState({ stations: response.data.network.stations }));
}
onSelectStation(stationKey) {
const { activeStations } = this.state;
const activeStationsEdit = activeStations;
if (!activeStations.includes(stationKey)) {
activeStationsEdit.push(stationKey);
} else {
activeStationsEdit.splice(activeStations.indexOf(stationKey), 1);
}
this.setState({ activeStations: activeStationsEdit });
}
renderStations() {
return this.state.stations.map((stations) =>
<StationDetails
activeStations={this.state.activeStations}
pressStatus={this.state.pressStatus}
key={stations.id}
stations={stations}
stationId={stations.id}
onSelectStation={this.onSelectStation}
>
{stations.name}
</StationDetails>
);
}
render() {
return (
<ScrollView style={{ flex: 1, marginTop: 20 }}>
{this.renderStations()}
</ScrollView>
);
}
}
StationDetails
类
import React from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
const StationDetails = ({ stations, activeStations, stationId, onSelectStation }) => {
const { headerTextStyle, leftPartStyle, container, pressedStyle, buttonStyle } = styles;
return (
<View style={container}>
<View style={leftPartStyle}>
<Text style={headerTextStyle}>
{stations.name}
</Text>
<Text>
Free bikes: {stations.free_bikes}
</Text>
</View>
<TouchableOpacity
onPress={() => onSelectStation(stationId)}
style={activeStations.includes(stations.id) ? pressedStyle : buttonStyle}
/>
</View>
);
}
const styles = {
container: {
flex: 1,
flexDirection: 'row',
marginBottom: 10
},
leftPartStyle: {
flex: 3,
flexDirection: 'column',
justifyContent: 'space-between'
},
pressedStyle: {
backgroundColor: 'green',
flex: 1,
},
headerTextStyle: {
fontSize: 18
},
buttonStyle: {
backgroundColor: 'skyblue',
flex: 1,
}
};
export default StationDetails;