How use this hook inside a react.component class?

Hi. I have a problem, I’m using react navigation and I have a formula in which I need to pass a parameter to my const through a textInput automatically.

My operation, I need calculate the area from a circunference and validate if the result is impar or par:

const [valid, setValid] = React.useState('');

  const [invalid, setInvalid] = React.useState('');

  const [text, setText] = React.useState('');

  const pi = 3.1415;

  const total = (value) => {

    const result = (pi * (value / (2 * pi))*(value / (2 * pi)) ).toFixed(2);

    const numint = (pi * (value / (2 * pi))*(value / (2 * pi)) ).toFixed(0);

    const rest = numint % 2;

    

    var validation;

    const invalido = " ✘  ";

    const valido = " ✔  ";

    if(rest == 0){

      validation = valido;

      setInvalid('');

      setValid(validation);

    }else{

      validation = invalido;

      setInvalid(validation);

      setValid('');

    }

    setText(result);

  };
export default class Calculus extends React.Component {
  render(){
                                
        return( 
           <ScrollView style={styles.container}>    
                <LinearGradient style={styles.background} />
               <View>
                    <Text style={{alignSelf:"center", color: "green"}}>{valid}<Text style={{color: "red"}}>{invalid}</Text></Text>

                     <TextInput placeholder="  Area" keyboardType="numeric" onChangeText = {total} />

       </View>
 </Scrollview>
}

I need to pass the “total” parameter to the formula, I tried to put that formula in a function and pass it to it but it didn’t work, and show “invalid” or “valid” parameters; I don’t understand how to do it. This only works in a function but I need this in my class react.component.

Thanks

Hi @santiagomilliongloba

You have some typos in your component code. If I tidy it up a bit it looks like this (by the way, prettier is a good way to automatically format your code nicely, but the syntax needs to be correct first):

export default class Calculus extends React.Component {
  render() {
    return (
      <ScrollView style={styles.container}>
        <LinearGradient style={styles.background} />
        <View>
          <Text style={{ alignSelf: "center", color: "green" }}>{valid}</Text>
          <Text style={{ color: "red" }}>{invalid}</Text>

          <TextInput
            placeholder="  Area"
            keyboardType="numeric"
            onChangeText={total}
          />
        </View>
      </ScrollView>
    );
  }
}

Unfortunately you cannot use a hook in a class component. But you can convert a class component to a function component and then use the hook in the function component. e.g. here is your class component converted to a function component:

export default function Calculus() {
  return (
    <ScrollView style={styles.container}>
      <LinearGradient style={styles.background} />
      <View>
        <Text style={{ alignSelf: "center", color: "green" }}>{valid}</Text>
        <Text style={{ color: "red" }}>{invalid}</Text>

        <TextInput
          placeholder="  Area"
          keyboardType="numeric"
          onChangeText={total}
        />
      </View>
    </ScrollView>
  );
}

By the way, something like this is likely to cause bugs later:

const [valid, setValid] = React.useState('');
const [invalid, setInvalid] = React.useState('');

It would generally be better to have only valid and set that to true or false. If it’s true, display the check mark and if it’s false, display the cross. Otherwise you might in future forget to set both valid and invalid at some point in your code and you might end up displaying ✔✘ or nothing.

Also here:

    const result = (pi * (value / (2 * pi))*(value / (2 * pi)) ).toFixed(2);
    const numint = (pi * (value / (2 * pi))*(value / (2 * pi)) ).toFixed(0);

Instead of doing the same calculation twice you could do something like this:

    const result = pi * (value / (2 * pi)) * (value / (2 * pi));
    const numInt = result.toFixed(0);
    // [...]
    setText(result.toFixed(2));
1 Like

Hi, thank you very much, how unfortunate that hooks cannot be used, and unfortunately there are things in the application that prevent me from having only one function.
The corrections to the mathematical operation helped me a lot (which is not exactly that, it is much more complex and secret, is an algoryth of my invention, for a filter)
I understood what you meant, I just did this and it worked, but I have a problem.

export default class Calculus extends React.Component {
    return(
        <Calculate />
    );
}

function Calculate() {
  return (
    <ScrollView style={styles.container}>
      <LinearGradient style={styles.background} />
      <View>
        <Text style={{ alignSelf: "center", color: "green" }}>{valid}</Text>
        <Text style={{ color: "red" }}>{invalid}</Text>

        <TextInput
          placeholder="  Area"
          keyboardType="numeric"
          onChangeText={total}
        />
      </View>
    </ScrollView>
  );
}

My problem is the _renderModalContent, state and _renderButton, these only functions in a class react.component:


_renderModalContent = () => (      
  <View style={styles.modalContent} collapsable={false}>
    
    <View style={{flex: 3, flexDirection: 'row'}}>
      <View style={{flex: 0.2}}><Image source={icono} /></View>
      <View style={{flex: 2.6}}>
        <Text style={styles.tituloTerminos}>{highlight(' Acerca del algoritmo ')}</Text>
      </View>
      <View style={{flex: 0.2}}>
        {this._renderButton(
          <Text 
           style={{
            color: "grey", 
            textAlign: "left"
          }}> X</Text>, 
          () => this.setState({ visibleModal: null }))
          }
      </View>
    </View>
    <View style={{ flex: 1 }}>
          <TouchableOpacity>
            <Swipeable />
          </TouchableOpacity>
    </View>
  </View>
);

state = {
  visibleModal: null,
  item: null,
};

_renderButton = (text, onPress) => (
  <TouchableOpacity onPress={onPress}>
    <View style={styles.button}>
      <Text>{text}</Text>
    </View>
  </TouchableOpacity>
);
export default class Calculus extends React.Component {
  return(
   <View style={styles.checkboxContainer}>
      <View style={{flexDirection: "column"}}>
              <View style={{flexDirection: "row"}}><Text>---------</Text></View>
              <View style={{flexDirection: "row"}}><MyCheckbox /></View>
              </View>
              <View style={{flexDirection: "column"}}>
                <TouchableHighlight>
                  <View>
                    {this._renderButton(
                       <Text style={{
                          color: "#2D6795"}}>
                          Apruebo y acepto los resultados
                       </Text>, 
                        () =>
                      this.setState({ visibleModal: 1 })
                    )}
                    <Modal isVisible={this.state.visibleModal === 1}>
                        {this._renderModalContent()}                   
                    </Modal>
                  </View>
                </TouchableHighlight>
       </View>
    </View>
    );
}

How convert _renderModalContent, state and _renderButton in hooks for my function?

It took me about 2 months to create that code, it causes a modal to appear when pressing a link in my application and within this modal a swipeable appears with 70 pages explaining about this form, I can’t lose that job for because of the incompatibility between a function and a class react.component. :frowning:

There’s no reason for the above component, as written, to be a class. It can just as well be a function:

export default function Calculus() {
  return <Calculate />;
}

But it does not really make a difference in this case.

What do you think of the following? (Untested):

function MyButton({ onPress, children }) {
  return (
    <TouchableOpacity onPress={onPress}>
      <View style={styles.button}>{children}</View>
    </TouchableOpacity>
  );
}

function ModalContent({ setModalIsVisible }) {
  return (
    <View style={styles.modalContent} collapsable={false}>
      <View style={{ flex: 3, flexDirection: "row" }}>
        <View style={{ flex: 0.2 }}>
          <Image source={icono} />
        </View>
        <View style={{ flex: 2.6 }}>
          <Text style={styles.tituloTerminos}>
            {highlight(" Acerca del algoritmo ")}
          </Text>
        </View>
        <View style={{ flex: 0.2 }}>
          <MyButton onPress={() => setModalIsVisible(false)}>
            <Text style={{ color: "grey", textAlign: "left" }}>X</Text>
          </MyButton>
        </View>
      </View>
      <View style={{ flex: 1 }}>
        <TouchableOpacity>
          <Swipeable />
        </TouchableOpacity>
      </View>
    </View>
  );
}

export default function Calculus() {
  const [modalIsVisible, setModalIsVisible] = useState(false);
  const [item, setItem] = useState(null);

  return (
    <View style={styles.checkboxContainer}>
      <View style={{ flexDirection: "column" }}>
        <View style={{ flexDirection: "row" }}>
          <Text>---------</Text>
        </View>
        <View style={{ flexDirection: "row" }}>
          <MyCheckbox />
        </View>
      </View>
      <View style={{ flexDirection: "column" }}>
        <TouchableHighlight>
          <View>
            <MyButton onPress={() => setModalIsVisible(true)}>
              <Text style={{ color: "#2D6795" }}>
                Apruebo y acepto los resultados
              </Text>
            </MyButton>
            <Modal isVisible={modalIsVisible}>
              <ModalContent setModalIsVisible={setModalIsVisible} />
            </Modal>
          </View>
        </TouchableHighlight>
      </View>
    </View>
  );
}
1 Like

Hi. :smiley:
First of all, thanks for your help, it has helped me a lot.

Regarding this, I thought that it is necessary, I have many views, i’m using react-navigation-stack, according to my first tutorial it had to be with classes, but now that you mention it to me and that I am understanding the code better, I realize that you are right and I’m complicating the life with the classes

Two hours ago I tried something different although longer, I tested that and my app worked. But your code, dividing Button and ModalContent in diferent functions looks more simple and tidy.

Part of my new code:

function Calculate() {
const [visibleModal, setVisibleModal] = useState(null);

  _renderModalContent = () => (      
    <View style={styles.modalContent} collapsable={false}>
      <View style={{flex: 3, flexDirection: 'row'}}>
        <View style={{flex: 0.2}}><Text></Text></View>
        <View style={{flex: 2.6}}>
          <Text style={styles.tituloTerminos}>{highlight(' Explicación de los algoritmos ')}</Text>
        </View>
        <View style={{flex: 0.2}}>

          {_renderButton(
            <Text 
             style={{
              color: "grey", 
              textAlign: "left"
            }}> X</Text>, 
            () => setVisibleModal(null))
            }
        </View>
      </View>
      <View style={{ flex: 1 }}>
            <TouchableOpacity>
              <Swipeable />
            </TouchableOpacity>
      </View>
    </View>

  ); 

_renderButton = (text, onPress) => (
  <TouchableOpacity onPress={onPress}>
    <View style={styles.button}>
      <Text>{text}</Text>
    </View>
  </TouchableOpacity>
);

  return(
   <View style={styles.checkboxContainer}>
      <View style={{flexDirection: "column"}}>
              <View style={{flexDirection: "row"}}><Text>---------</Text></View>
              <View style={{flexDirection: "row"}}><MyCheckbox /></View>
              </View>
              <View style={{flexDirection: "column"}}>
                <TouchableHighlight>
                  <View>
                    {_renderButton(
                       <Text style={{
                          color: "#2D6795"}}>
                          Apruebo y acepto los resultados
                       </Text>, 
                          () => setVisibleModal(1)
                    )}
                      <Modal isVisible={visibleModal === 1}>
                          {_renderModalContent()}                   
                      </Modal>
                  </View>
                </TouchableHighlight>
       </View>
    </View>

}

I delete:

state = {
  visibleModal: null,
  item: null,
};

and replace it for:
const [visibleModal, setVisibleModal] = useState(null);

I delete all “this.” for:
this._renderModalContent() or this._renderButton()

and I delete all this.setState like that:
this.setState({ visibleModal: 1 })

and replacing it for:
() => setVisibleModal(1)

Now I will apply your suggested code and delete the class react.component. Thanks so much.

1 Like