为什么颜色会多次更新

时间:2018-05-18 19:33:10

标签: react-native lifecycle

为什么我的随机颜色会多次更新?是通过生命周期事件控制此行为的正确方法吗?



import React from 'react';
import { StyleSheet, Text, ScrollView, FlatList, SectionList, View, Button, SegmentedControlIOS } from 'react-native';
import contacts, {compareNames} from './contacts';
import {Constants} from 'expo';
import PropTypes from 'prop-types'

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}


const Row=(props)=>(
  <View style={styles.row}>
    <Text style={{color:props.color}} >{props.name}</Text>
    <Text >{props.phone}</Text>
  </View>
)

const renderItem=(obj)=> {

     return(<Row  {...(obj.item)} color={getRandomColor()} />)

}

const ContactsList = props => {
  const renderSectionHeader=(obj) =><Text>{obj.section.title}</Text>
    const contactsByLetter = props.contacts.reduce((obj, contact) =>{
     const firstLetter = contact.name[0].toUpperCase()
     return{
       ...obj,
       [firstLetter]: [...(obj[firstLetter] || []),contact],
     }
   },{})

   const sections = Object.keys(contactsByLetter).sort().map(letter=>({
      title: letter,
      data: contactsByLetter[letter],
   }))

  return(
  <SectionList
    keyExtractor = { (item, key) => key.toString() }
    renderItem={renderItem}
    renderSectionHeader={renderSectionHeader}
    sections={sections}
  />
)}

ContactsList.propTypes ={
  renderItem: PropTypes.func,
  renderSectionHeader: PropTypes.func,
  contacts: PropTypes.array,
  sections: PropTypes.func
}

export default class App extends React.Component {
  state={show: false, selectedIndex: 0, contacts: contacts}

  toggleContacts=()=>{
    this.setState({show:!this.state.show})
  }

  sort=()=>{
    this.setState({contacts: [...this.state.contacts].sort(compareNames)})
  }

  render() {
    return (
      <View style={styles.container}>
        <Button title="toggle names" onPress={this.toggleContacts}  />
        <Button title="sort" onPress={this.sort}  />
        <SegmentedControlIOS
          values={['ScrollView', 'FlatList','SectionList']}
          selectedIndex={this.state.selectedIndex}
          onChange={(event) => {
            this.setState({selectedIndex: event.nativeEvent.selectedSegmentIndex});
          }} />
        {this.state.show && this.state.selectedIndex === 0 &&
          <ScrollView >
            {this.state.contacts.map(contact=>(
              <Row  {...contact}/> ))}
          </ScrollView>}
        {this.state.show && this.state.selectedIndex === 1 &&
          <FlatList
            data={this.state.contacts}
            keyExtractor = { (item, index) => index.toString() }
            renderItem={renderItem}>
          </FlatList>}
        {this.state.show && this.state.selectedIndex === 2 &&
          <ContactsList
            contacts={this.state.contacts}>
          </ContactsList>}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    // alignItems: 'flex-start',
    paddingTop: Constants.statusBarHeight + 25,
  },
  row: {
    padding:20,
  },
});
&#13;
const NUM_CONTACTS = 10

const firstNames = ['Emma','Noah','Olivia','Liam','Ava','William','Sophia','Mason','Isabella','James','Mia','Benjamin','Charlotte','Jacob','Abigail','Michael','Emily','Elijah','Harper','Ethan','Amelia','Alexander','Evelyn','Oliver','Elizabeth','Daniel','Sofia','Lucas','Madison','Matthew','Avery','Aiden','Ella','Jackson','Scarlett','Logan','Grace','David','Chloe','Joseph','Victoria','Samuel','Riley','Henry','Aria','Owen','Lily','Sebastian','Aubrey','Gabriel','Zoey','Carter','Penelope','Jayden','Lillian','John','Addison','Luke','Layla','Anthony','Natalie','Isaac','Camila','Dylan','Hannah','Wyatt','Brooklyn','Andrew','Zoe','Joshua','Nora','Christopher','Leah','Grayson','Savannah','Jack','Audrey','Julian','Claire','Ryan','Eleanor','Jaxon','Skylar','Levi','Ellie','Nathan','Samantha','Caleb','Stella','Hunter','Paisley','Christian','Violet','Isaiah','Mila','Thomas','Allison','Aaron','Alexa','Lincoln']

const lastNames = ['Smith','Jones','Brown','Johnson','Williams','Miller','Taylor','Wilson','Davis','White','Clark','Hall','Thomas','Thompson','Moore','Hill','Walker','Anderson','Wright','Martin','Wood','Allen','Robinson','Lewis','Scott','Young','Jackson','Adams','Tryniski','Green','Evans','King','Baker','John','Harris','Roberts','Campbell','James','Stewart','Lee','County','Turner','Parker','Cook','Mc','Edwards','Morris','Mitchell','Bell','Ward','Watson','Morgan','Davies','Cooper','Phillips','Rogers','Gray','Hughes','Harrison','Carter','Murphy']

// generate a random number between min and max
const rand = (max, min = 0) => Math.floor(Math.random() * (max - min + 1)) + min

// generate a name
const generateName = () => `${firstNames[rand(firstNames.length - 1)]} ${lastNames[rand(lastNames.length - 1)]}`

// generate a phone number
const generatePhoneNumber = () => `${rand(999, 100)}-${rand(999, 100)}-${rand(9999, 1000)}`

// create a person
const createContact = () => ({name: generateName(), phone: generatePhoneNumber()})

// compare two contacts for alphabetizing
export const compareNames = (contact1, contact2) => contact1.name > contact2.name

// add keys to based on index
const addKeys = (val, key) => ({key, ...val})

// create an array of length NUM_CONTACTS and alphabetize by name
export default Array.from({length: NUM_CONTACTS}, createContact).map(addKeys)
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

看起来您的组件多次触发渲染方法。这种情况主要发生在使用setState方法时,因为每次state更改时都会触发渲染方法。

您可以有两个选项来处理此问题:

1)确定您的组件被重新呈现的位置,并在不需要此行为时对其进行处理。您可以使用console.log进行调试。

2)如果仅在componentDidMount方法中调用随机方法,则可以避免多次调用随机方法。由于componentDidMount在组件生命周期中仅被调用一次,因此当组件重新呈现时,只有当它再次安装时,才会触发其中的所有函数。 (我认为这是解决方案)

如果有帮助,请告诉我。