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?

Answer

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>


Source: stackoverflow