how to change date localization and displayed a new localized date?
const Locale = () => {
return (
<div>
<button onClick={() => moment.locale("en")}>English</button>
<button onClick={() => moment.locale("de")}>German</button>
<p>{moment().format("LLLL")}</p>
</div>
);
};
codesandbox example https://codesandbox.io/s/vigorous-violet-v0hvf
Here is a codesandbox with a working example https://codesandbox.io/s/peaceful-lumiere-97yto
In react if you want the component to re-render again you should make some changes to the state.
const deMoment = moment().locale("de").format("LLLL");
const enMoment = moment().locale("en").format("LLLL");
const Locale = () => {
const [momentDate, setMomentDate] = useState(deMoment);
useEffect(() => {}, [momentDate]);
return (
<div>
<button onClick={() => setMomentDate(enMoment)}>English</button>
<button onClick={() => setMomentDate(deMoment)}>German</button>
<p>{momentDate}</p>
</div>
);
};
Moment.js locale will only gets applied to new instance created after updating. So I have maintained the locale in state and I keep updating it on button click.
import React, { useState } from "react";
import moment from "moment";
const Locale = () => {
let [loc, updateLoc]= useState("en")
return (
<div>
<button onClick={() => updateLoc("en")}>English</button>
<button onClick={() => updateLoc("de")}>German</button>
<p>{moment.locale(loc) && moment().format("LLLL")}</p>
</div>
);
};
export default Locale;
You will have to notify that moment object's locale is updated.
const Locale = () => {
const [currentMoment, setCurrentMoment] = useState(moment().format("LLLL"));
const updateMomentEN = () => {
moment.locale("en");
setCurrentMoment(moment().format("LLLL"));
};
const updateMomentDE = () => {
moment.locale("de");
setCurrentMoment(moment().format("LLLL"));
};
return (
<div>
<button onClick={updateMomentEN}>English</button>
<button onClick={updateMomentDE}>German</button>
<p>{currentMoment}</p>
</div>
);
};
here after every time locale is updated, we are updating currentMoment based on new locale. Then useState does the notifying work.
Related
I have a problem and I need you to help me understand it. I am using ReactJS and I am building a simple CRUD Todo App. I Want to store my todos in local storage.
The data is saved there and I can see it but after the refresh it is emptying my local storage.
What am I doing wrong?
Something that I notice is that from the first time when I open the app (first rendering), local storage is creating the storage space without adding a todo.
Could I have missed something in my code that makes it reset it or empty it when the page is rendered?
import React, { useState, useEffect } from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import {
faCheck,
faPen,
faPlus,
faTrashCan,
} from "#fortawesome/free-solid-svg-icons";
import "./App.css";
import { faCircleCheck } from "#fortawesome/free-regular-svg-icons";
function App() {
const [todos, setTodos] = useState([]);
const [todo, setTodo] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
useEffect(() => {
const json = window.localStorage.getItem("todos");
const loadedTodos = JSON.parse(json);
if (loadedTodos) {
setTodos(loadedTodos);
}
}, []);
useEffect(() => {
const json = JSON.stringify(todos);
window.localStorage.setItem("todos", json);
}, [todos]);
function handleSubmit(e) {
e.preventDefault();
const newTodo = {
id: new Date().getTime(),
text: todo,
completed: false,
};
setTodos([...todos].concat(newTodo));
setTodo("");
}
function deleteTodo(id) {
const updatedTodos = [...todos].filter((todo) => todo.id !== id);
setTodos(updatedTodos);
}
function toggleComplete(id) {
let updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
setTodos(updatedTodos);
}
function submitEdits(id) {
const updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.text = editingText;
}
return todo;
});
setTodos(updatedTodos);
setTodoEditing(null);
}
return (
<div className="App">
<div className="app-container">
<div className="todo-header">
<form onSubmit={handleSubmit}>
<input
type="text"
name="todo-input-text"
placeholder="write a todo..."
onChange={(e) => {
setTodo(e.target.value);
}}
value={todo}
/>
<button>
<FontAwesomeIcon icon={faPlus} />
</button>
</form>
</div>
<div className="todo-body">
{todos.map((todo) => {
return (
<div className="todo-wrapper" key={todo.id}>
{todo.id === todoEditing ? (
<input
className="edited-todo"
type="text"
onChange={(e) => setEditingText(e.target.value)}
/>
) : (
<p className={todo.completed ? "completed" : "uncompleted"}>
{todo.text}
</p>
)}
<div className="todo-buttons-wrapper">
<button onClick={() => toggleComplete(todo.id)}>
<FontAwesomeIcon icon={faCircleCheck} />
</button>
{todo.id === todoEditing ? (
<button onClick={() => submitEdits(todo.id)}>
<FontAwesomeIcon icon={faCheck} />
</button>
) : (
<button onClick={() => setTodoEditing(todo.id)}>
<FontAwesomeIcon icon={faPen} />
</button>
)}
<button
onClick={() => {
deleteTodo(todo.id);
}}
>
<FontAwesomeIcon icon={faTrashCan} />
</button>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}
export default App;
You should be loading todos from localStorage on the Component mount if they are available in localStorage like this,
const loadedTodos = localStorage.getItem("todos")
? JSON.parse(localStorage.getItem("todos"))
: []; // new
const [todos, setTodos] = useState(loadedTodos); // updated
And then you don't have to mutate the state using setTodos(loadedTodos) in the useEffect.
Just remove this useEffect , from the code:
// that useEffect should be removed
useEffect(() => {
const json = window.localStorage.getItem("todos");
const loadedTodos = JSON.parse(json);
if (loadedTodos) {
setTodos(loadedTodos);
}
}, []);
You can check this in the working CodeSandbox as well.
I think your second useEffect is causing it to reset.
Move that the useEffect logic to a separate function.
And instead of calling setTodos, call that function, update the storage, and then call setTodos from that function.
If you call the setTodos function with a callback function and spread operator like this it should work:
useEffect(() => {
const json = window.localStorage.getItem("todos");
const loadedTodos = JSON.parse(json);
if (loadedTodos) {
// set local storage like this
setTodos( prevTodos => [...prevTodos, ...loadedTodos] );
}}, []);
So I have two radio button images, one checked and one not. I am trying to persist the change of state to view the corresponding image on button click for each of the inputs.
Please help.
Here's my code:
import React, { useState, useEffect } from 'react';
const Option = (props) => {
const img1 = <img alt='' src='/radio-active.png' className='radio__img' />;
const img2 = <img alt='' src='/radio-inactive.png' className='radio__img' />;
const [state, setState] = useState(false);
const handleStateChange = () => {
state === true ? setState(false) : setState(true);
};
useEffect(() => {
setState(JSON.parse(window.localStorage.getItem('state')));
}, []);
useEffect(() => {
window.localStorage.setItem('state', state);
}, [state]);
return (
<div className='option'>
<div className='radio'>
<button className='radio__button' onClick={handleStateChange}>
{state ? img1 : img2}
</button>
<p className='option__text radio__text'>{props.optionText}</p>
</div>
<button
className='button button--link'
onClick={(e) => {
props.handleDeleteOption(props.optionText);
}}
>
remove
</button>
</div>
);
};
export default Option;
All of your Option components are saving the state using the same key ("state"). You'll want each Option to have its own saved state. For each Option, add a new "optionName" property that is the key you want to use when saving the option's value to local storage.
// Change these:
window.localStorage.setItem('state', state);
setState(JSON.parse(window.localStorage.getItem('state')));
// To these:
window.localStorage.setItem(props.optionName, state);
setState(JSON.parse(window.localStorage.getItem(props.optionName)));
To show my question here is a Demo code.(I'm using React Hooks and Antd.)
My Question is:
when currId state is changed and I click MyButton the state is still '' (which is the initial state). onClick event is an arrow function and in it is showModal with params, if there's no params currId can be seen changed but now with params state isn't changed. May I ask what is the reason of it and how I can get changed currId in showModal?
(operation: click 'Change CurrId' button --> setCurrId('12345') ---> click 'MyButton' ---> console.log(currId))
import React, { useState } from 'react'
import 'antd/dist/antd.css';
import { Button} from 'antd';
const MyComponent= () => {
const [currId, setCurrId] = useState('');
const changeCurrId= async () => {
setCurrSolutionId('12345');
}
const showModal = async (num:any) => {
console.log("☆ currid:");// I cannot get the currId state '12345' but ''
console.log(currId);
console.log("☆ num:");//I can get the num params 5
console.log(num);
};
return (
<>
<Button type="primary" onClick={changeCurrId}>Change CurrId</Button>
<Button type="primary" onClick={() => {showModal(5)}}>MyButton</Button>
</>
);
}
const MyComponent= () => {
const [currId, setCurrId] = useState('');
const changeCurrId= () => {
setCurrId('12345');
}
const showModal = (num:string) => {
console.log("☆ currid:");
console.log(num);
};
const changeCurrentIdAndShowModal = (id : string) => {
setCurrId(id);
showModal(id)
console.log("☆ id:");
console.log(id);
};
return (
<>
<Button type="primary" onClick={() => changeCurrId()}>MyButton</Button>
<Button type="primary" onClick={() => showModal('5')}>MyButton</Button>
<Button type="primary" onClick={() => changeCurrentIdAndShowModal('12345')}>MyButton</Button>
</>
);
}
Is this the intention you want?
Good day Everyone,
I'm trying to run a query that increases a number whenever a button is clicked. I'm using a course from udemy is kinda old and our setup/installation is different. Please look at my code down below.
let count = 0;
const addOne = () => {
count++;
rendertheCounterApp();
};
const minus =() => {
console.log('Minus',);
}
const Reset = () => {
console.log ('Reset');
};
const rendertheCounterApp = () => {
const App = () => {
return (
<div className='App'>
<h1>Toggler {count} </h1>
<button onClick ={addOne}> +1 </button>
<button onClick={minus}>-1</button>
<button onClick ={Reset}>Rest</button>
</div>
);
};
export default App;
};
rendertheCounterApp();
is there any way I can modify that code to make the number increase whenever I click on the button?
Thanks in advance.
You need to have state to store the count and you can increase or decrease the count without creating any special functions. Try something like:
import React, { useState } from 'react';
const RenderTheCounterApp = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Add</button>
<button onClick={() => setCount(count - 1)}>Subtract</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};
The "Bad button" only works once, since it's not controlling the same "value" as the "Good button". What am I missing here?
const Test = () => {
const [value, setValue] = useState(0)
const [view, setView] = useState()
const add = () => setValue(value + 1)
const badButton = () => {
return (
<div>
<button onClick={add}>Bad button</button>
</div>
)
}
return (
<div>
{value}
<button onClick={add}>Good button</button>
{view}
<button onClick={() => setView(badButton)}>show bad button</button>
</div>
)
}
Thanks for replying, I'm going to use the flag method as suggested. But I would still like to know why the two buttons don't work the same way in this original case.
Check this sandbox
I feel it's the right way to handle such a usecase. Instead of storing component itself in state. I replaced it with a boolean. By default it will be false and badButton will be hidden, on click of showBadButton, i'm setting the view state true and bad button will come into picture. Actually Its a good buton now. Check it out.
I would use view as a flag to show/hide BadButton component, I have created a demo that showcase the following code snippet:
import React, { useState } from 'react';
import { render } from 'react-dom';
import './style.css';
const Test = () => {
const [value, setValue] = useState(0)
const [view, setView] = useState(false)
const add = () => setValue(value + 1)
const BadButton = () => {
return (
<button onClick={add}>Bad button</button>
)
}
return (
<>
{value}
<button onClick={add}>Good button</button>
{view ? BadButton() : null}
<button onClick={() => setView(!view)}>
{view ? 'hide' : 'show'} bad button
</button>
</>
)
}
render(<Test />, document.getElementById('root'));
Welcome to StackOverflow