Reputation: 941
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?
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);
export let unitState = "°C";
export function setUnitState(unit) {
(unit==="°C") ? unitState="°C" : unitState="°F";
}
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
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
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
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