hexaquark
hexaquark

Reputation: 941

ReactJs change text upon button click problem

I have a large project with multiple files. I want a button to render the content of some other components upon clicking. I am trying to understand why the following does not work, and what could I do to make it work instead?

Index.js

import React from "react";
import ReactDOM from "react-dom";

import { unitState, setUnitState } from './changeUnit.js'


function App() {
  return (
    <div>
      <h1>{unitState}</h1>

      <button onClick={setUnitState("°C")}>°C</button>
      <button onClick={setUnitState("°F")}>°F</button>
    </div>
  );
}

// ------
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

changeUnit.js

export let unitState = "°C";
export function setUnitState(unit) {
    (unit==="°C") ? unitState="°C" : unitState="°F";
}

with codesandbox link here


Currently, upon clicking any of the buttons the text does not change. But the code does reach inside the setUnitState method. I suspect that is because the main component is not rerendering. I tried to change my changeUnit.js code to

import App from './index.js';

export let unitState = "°C";
export function setUnitState(unit) {
    (unit==="°C") ? unitState="°C" : unitState="°F";
    App.forceUpdate();
}

but I get the error _index.default.update is not a method.

I have tried to use the useState hook from React but I just can't make it work for the life of me. I have tried many combinations but it seems that I can't return the setState function as a return from the custom hook.

Does anyone know how I can solve this problem?

Upvotes: 2

Views: 647

Answers (3)

mitomed
mitomed

Reputation: 2066

I think you should just use setState, it might be the case that you were trying to call the setState without the lambda?

import React, { useState } from "react";
import ReactDOM from "react-dom";

function App() {
  const [unitState, setUnitState] = useState("C");

  return (
    <div>
      <h1>{unitState}</h1>

      <button onClick={() => setUnitState("C")}>C</button>
      <button onClick={() => setUnitState("F")}>F</button>
    </div>
  );
}

// ------
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/changeunitstate-forked-zbrym

Upvotes: 1

Zsolt Meszaros
Zsolt Meszaros

Reputation: 23189

I'm not sure why you're not using the useState hook, or what went wrong with your custom hook.

With useState():

function App() {
  let [unitState, setUnitState] = React.useState('°C')
  
  return (
    <div>
      <h1>{unitState}</h1>
      <button onClick={() => setUnitState('°C')}>°C</button>
      <button onClick={() => setUnitState('°F')}>°F</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

With custom hook:

function App() {
  let { unitState, setCelsius, setFahrenheit } = useSwitch()
  
  return (
    <div>
      <h1>{unitState}</h1>
      <button onClick={setCelsius}>°C</button>
      <button onClick={setFahrenheit}>°F</button>
    </div>
  );
}

function useSwitch() {
  let [unitState, setUnitState] = React.useState('°C')
  let setCelsius = () => setUnitState('°C')
  let setFahrenheit = () => setUnitState('°F')
  return { unitState, setCelsius, setFahrenheit }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 2

Claeusdev
Claeusdev

Reputation: 503

I'm guessing you probaly weren't using useState right. this is fairly simple with use state.

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";

// import { unitState, setUnitState } from "./changeUnit.js";

function App() {
  const [unitState, setUnitState] = useState("°C");
  return (
    <div>
      <h1>{unitState}</h1>

      <button onClick={() => setUnitState("°C")}>°C</button>
      <button onClick={() => setUnitState("°F")}>°F</button>
    </div>
  );
}

// ------
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Upvotes: 1

Related Questions