更改列表中“已切换”元素的样式,react-native

时间:2018-09-09 19:03:59

标签: reactjs list react-native styles state

我无法更改列表中仅一个元素的样式。 下面是我的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

1 个答案:

答案 0 :(得分:0)

您正在尝试从Main.activeStations设置StationDetails的状态,这是不可取的。没什么要记住的

  • Main的activeStations处于本地组件级别状态。
  • 您不应该尝试从子组件中对其进行突变。
  • 由于您将activeStations的突变Main.activeStations状态分配给StationDetails,因此ReactNative(RN)在对帐过程中没有发现状态差异,因此不会重新呈现{{ 1}}。
  • 我们需要RN重新渲染StationDetails,以使其显示按钮等的正确样式。
  • setState上的文档

这就是我要做的

  • 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