Expo - Invalid hook call inside function components

Asked

Viewed 88 times

0

I was learning Expo, and I needed to create a dynamic list of counters.

On my screen I have a button + that adds other squares, and each of these squares has a counter inside them, from what I understand of the tutorials, is that each of these components needs a Hook so that they can change their state.

Each separate component works, but when I use the two Hooks on the same page, I have a problem Invalid hook call. Hooks can only be called Inside of the body of a Function Component. This could happen for one of the following reasons

I’ve read the expo and React documentation on the Hooks and I couldn’t get out of place.

I use the default project generated by the expo, with only changes in Homescreen.js. Follow the code:

Homescreen.js

import React, { useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View, FlatList } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';

import { Square } from '../components/Square';

export default function HomeScreen(props){

  const [participantes, setParticipantes] = useState([]);

  const adicionarParticipante = () => {
     setParticipantes([...participantes, Square(props)]);
  }

  return (
    <View style={styles.container}>
    <ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>

    <View style={styles.getStartedContainer}>
    <TouchableOpacity onPress={adicionarParticipante} style={styles.button}>
    <Text style={styles.buttonPlacar}>+</Text>
    </TouchableOpacity>
    <FlatList data={participantes} showsVerticalScrollIndicator = {false}
    renderItem= { ({ item }) => item }/>
    </View>

    </ScrollView>
    </View>
    );
}

HomeScreen.navigationOptions = {
  header: null,
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  contentContainer: {
    paddingTop: 30,
  },
  getStartedContainer: {
    alignItems: 'center',
    marginHorizontal: 50,
  },
  button: {
    backgroundColor: "#ffc107",
    padding: 20,
    height: 100,
    width: 100,
    justifyContent: 'center',
    borderRadius: 5,
  },
  buttonPlacar: {
    textAlign: 'center',
    fontSize: 20,
    color: 'white',
  }
});

Square js.

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Text, View, TouchableOpacity} from 'react-native';

export function Square(props) {

    const [count, setcount] = useState(0);

    const sqStyle = {
        backgroundColor: "#007bff",
        padding: 20,
        height: 100,
        width: 100,
        marginTop: 10,
        justifyContent: 'center',
        borderRadius: 5,
    };

    const tStyle = {
        textAlign: 'center',
        fontSize: 20,
        color: 'white',
    }

    return  <TouchableOpacity onPress={() => setcount(count+1)}> 
                <View style={sqStyle}>
                    <Text style={tStyle}>{count}</Text>
                </View>
            </TouchableOpacity>;
}

Square.propTypes = {
  count: PropTypes.int
};

From now on, thank you all for your time.

1 answer

0

I had not understood the real concept of the Hooks in React-on, my code missing only final alignment, was like this:

homescreen.js import React, { useState } from 'React'; import { Stylesheet, Text, Touchableopacity, View, Flatlist } from 'React-Native'; import { Scrollview } from 'React-Native-Gesture-Handler';

import { Square } from '../components/Square';

export default function HomeScreen(){

  const [participantes, setParticipantes] = useState([])

  const gera_cor = () => {
    var hexadecimais = '0123456789ABCDEF';
    var cor = '#';

    let aux = 0;
    // Pega um número aleatório no array acima
    for (var i = 0; i < 6; i++ ) {
    //E concatena à variável cor
        cor += hexadecimais[Math.floor(Math.random() * 16)];
    }
    return cor;
  }

  const adicionarPessoa = () => {
    const novo = {
      count : 1,
      cor   : gera_cor()
    }
    setParticipantes([...participantes, novo]);
  };

  const adicionarPedaco = (i) => {
    var p = participantes;
    p[i].count = p[i].count+1;
    setParticipantes([...p]);
  }

  return (
    <View style={styles.container}>
      <View style={styles.container} contentContainerStyle={styles.contentContainer}>
        <View style={styles.getStartedContainer}>
          <TouchableOpacity onPress={adicionarPessoa} style={styles.button}>
            <Text style={styles.buttonPlacar}>+</Text>
          </TouchableOpacity>
          <FlatList 
            style={styles.list}
            data={participantes} 
            keyExtractor={(item, index) => index.toString()}
            numColumns = {3}
            renderItem= { ({ item, index }) => Square(item, adicionarPedaco, index)} />
        </View>
      </View>
    </View>
  );
}

HomeScreen.navigationOptions = {
  header: null,
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignContent: 'stretch',
    backgroundColor: '#fff',
  },
  contentContainer: {
    paddingTop: 30,
  },
  getStartedContainer: {
    alignItems: 'center',
    marginHorizontal: 1,
  },
  button: {
    backgroundColor: "#ffc107",
    padding: 20,
    height: 100,
    width: 100,
    justifyContent: 'center',
    borderRadius: 5,
  },
  buttonPlacar: {
    textAlign: 'center',
    fontSize: 20,
    color: 'white',
  },
  list :{
    width: '100%'
  }
});

Square js.

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Text, View, TouchableOpacity} from 'react-native';

export function Square(pessoa, adiciona, i) {

    const sqStyle = {
        backgroundColor: pessoa.cor,
        padding: 20,
        height: 100,
        width: 100,
        marginTop: 5,
        marginBottom: 5,
        marginLeft: 5,
        marginRight: 5,
        justifyContent: 'center',
        borderRadius: 5,
    };

    const tStyle = {
        textAlign: 'center',
        fontSize: 20,
        backgroundColor: 'white',
        borderColor: 'grey',
        borderRadius : 10,
        borderWidth: 1,
        color: 'black',
    }

    return  <TouchableOpacity onPress={() => adiciona(i)}> 
                <View style={sqStyle}>
                    <Text style={tStyle}>{pessoa.count}</Text>
                </View>
            </TouchableOpacity>;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.