JorgeEstaAqui
JorgeEstaAqui

Reputation: 85

How to use react refs, callback pattern to update state

Currently, I'm trying to use a modal inside of a component to update the components state. I'm able to get the modal to open and I'm able to fill in the input values. Once I hit the add button, I'd like the state to be updated and the modal to close. This should cause new data to be showed in the main Exercise component.

However, when I try to add the new row the process hangs in the addWorkoutRow method and doesn't serve any errors. The button changes back to Add Workout but the modal doesn't close and the state doesn't update.

I've tried to use the setState callback with no luck. I'm pretty sure that my error between setting const newRow and calling the setModalVisible function I just haven't been able to step back far enough to see it.

import React, {Component} from 'react';
import {Modal, View, StyleSheet, TextInput, Text, TouchableOpacity} from 'react-native';

const ExerciseItem = (name, sets, reps, weight) => (
    <View style={styles.exerciseItem}>
      <Text style={styles.itemInput}>{name}</Text>
      <Text style={styles.itemInput}>{sets}</Text>
      <Text style={styles.itemInput}>{reps}</Text>
      <Text style={styles.itemInput}>{weight}</Text>
    </View>
  );

class Exercise extends Component {
  constructor() {
    super();

    this.state = {
      showCustomForm: false,
      showWeightsForm: !this.showCustomForm,
      modalVisible: false,
      rows: [],
      counter: 0,
    }

    this.addWorkoutRow = this.addWorkoutRow.bind(this);
  }
  setModalVisible(visible) {
    this.setState({modalVisible: visible})
  }
  addWorkoutRow() {
    const name = this.name._lastNativeText;
    const sets = this.sets._lastNativeText;
    const reps = this.reps._lastNativeText;
    const weight = this.weight._lastNativeText;

    const newRow = { name, sets, reps, weight };
    const rows = this.state.rows;

    rows.push(newRow);

    this.setState({ rows });
    this.setModalVisible(!this.state.modalVisible);
  }
  render() {
    const rows = []

    for (let i = 0; i < this.state.rows.length; i += i) {
      rows.push(<ExerciseItem 
        key={i} 
        name={this.state.rows[i].name} 
        sets={this.state.rows[i].sets}
        reps={this.state.rows[i].reps}
        weight={this.state.rows[i].weight}
      />);
    }

    return (
      <View style={styles.container}>
        <Text style={{fontSize: 20, color: '#fff', fontWeight: 'bold' }}>Workout</Text>
        <Modal
          style={styles.modalContainer}
          animationType="fade"
          transparent
          visible={this.state.modalVisible}
          onRequestClose={() => console.log('closed')}
          presentationStyle="overFullScreen"
        >
          <TextInput
            ref={(input) => { this.name = input; }} 
            style={styles.modalInputs}
            placeholderTextColor={'#fff'}
            placeholder={'Exercise Name'} />
          <TextInput
            ref={(input) => { this.sets = input; }} 
            style={styles.modalInputs}
            placeholderTextColor={'#fff'}
            placeholder={'Sets'} />
          <TextInput
            ref={(input) => { this.reps = input; }} 
            style={styles.modalInputs}
            placeholderTextColor={'#fff'}
            placeholder={'Reps'} />
          <TextInput
            ref={(input) => { this.weight = input; }} 
            style={styles.modalInputs}
            placeholderTextColor={'#fff'}
            placeholder={'Weight'} />
          <TouchableOpacity
            onPress={() => this.addWorkoutRow()}
            style={styles.modalBtn}>
            <Text style={styles.drkContent}>+</Text>
          </TouchableOpacity>
        </Modal>
        {rows}
        <View style={styles.btnContainer}>
          <TouchableOpacity 
            onPress={() => this.setModalVisible(!this.state.modalVisible)} 
            style={styles.btns}>
            <Text style={styles.drkContent}>Add Workout</Text>
          </TouchableOpacity>
        </View>
      </View>
    )
  }
}

export default Exercise

Here's my package.json

{
    "name": "PresentApp",
    "version": "0.0.1",
    "private": true,
    "scripts": {
        "start": "node node_modules/react-native/local-cli/cli.js start",
        "test": "jest",
        "lint": "eslint ./components"
    },
    "dependencies": {
        "babel-eslint": "^8.2.1",
        "eslint": "^4.17.0",
        "eslint-config-airbnb": "^15.1.0",
        "eslint-config-prettier": "^2.9.0",
        "eslint-plugin-import": "^2.8.0",
        "eslint-plugin-jsx-a11y": "^5.1.1",
        "eslint-plugin-react": "^7.6.1",
        "prettier": "^1.10.2",
        "prop-types": "^15.6.0",
        "react": "16.0.0",
        "react-native": "0.50.4",
        "react-native-router-flux": "^4.0.0-beta.24",
        "react-native-sound": "^0.10.4"
    },
    "devDependencies": {
        "babel-jest": "21.2.0",
        "babel-preset-react-native": "4.0.0",
        "eslint-plugin-prettier": "^2.6.0",
        "firebase": "^5.0.4",
        "jest": "21.2.1",
        "react-test-renderer": "16.0.0"
    },
    "jest": {
        "preset": "react-native"
    }
}

Upvotes: 2

Views: 524

Answers (1)

vahissan
vahissan

Reputation: 2332

In your for loop, you're incrementing like this i += i. This results in an infinite loop. That's why your component gets stuck in render. Change for loop increment to i += 1.

Upvotes: 2

Related Questions