)
}
const LoginForm = ({onLogin}) => {
//тут надо два состояния - для логина и для пароля;
const [stateLogin, setStateLogin] = useState("")
const [statePass, setStatePass] = useState("")
//кнопка логина должна быть disabled если одно из полей пустое
const disabled = stateLogin && statePass ? false : true
//по клику на кнопку запустить onLogin и передать туда
//текущее состояние login и password
return (
//
тут вместо h1 должна быть верстка: два инпута и кнопка login
)
}
/*Spoiler
Реализуйте компонент Spoiler, скрывающий контент и открывающий его по клику. Компонент будет получать 3 пропс:
header, который будет выводится всегда
open, может быть true или false, если написать в JSX без значения, это значит open={true}
вложенный контент, т. е. children, который отображается в открытом состоянии спойлера и не отображается в закрытом
Изначально компонент имеет состояние переданное через пропс open По клику на
в котором будет отображаться header должно меняться состояние на противоположное Обеспечьте условие, которое будет показывать или нет children.*/
const Spoiler = ({ header = "+", open = true, children }) => {
//напишите тут код
const [getOpen, setOpen] = useState(open)
return (
<>
)
}
}
/*Timer
Напишите компонент, в который передается через props количество секунд, а компонент при этом реализует обратный отсчет раз в секунду уменьшая количество секунд на 1. Останавливается на 0. Добавьте в компонент кнопку паузы.
Компонент должен отображать часы, минуты и секунды.*/
function Timer({pauseState = false, sec}){
const [pause, setPause] = useState(pauseState)
const [time, setTime] = useState(sec)
let timeout
useEffect(() => {
if (time > 0 && pause === false) {
timeout = setTimeout(() => {
console.log(time)
setTime(time - 1000)
}, 1000)
}
})
return (
{time/1000}
)
}
/*TimerControl
Напишите компонент, с тремя полями ввода (часы, минуты и секунды) и кнопкой Start, по которой будет стартовать компонент Timer*/
function Timer2({sec}){
const [pause, setPause] = useState(false)
const [time, setTime] = useState(sec)
console.log('Timer2' , time)
useEffect(()=>setTime(sec), [sec])
const timeoutRef = useRef()
useEffect(() => {
if (time.value > 0 && pause === false) {
timeoutRef.current = setTimeout(() => {
console.log(time.value)
setTime({value: time.value - 1000})
}, 1000)
console.log('timeout', timeoutRef.current)
}
}, [time, pause])
let pauseButtonText = pause ? "продолжить отсчёт" : "пауза"
let hours = Math.floor(time.value / (60 * 60 * 1000))
let minutes = Math.floor((time.value - (hours*60*60*1000))/(60*1000))
let seconds = Math.floor((time.value - (hours*60*60*1000) - (minutes*60*1000))/1000)
return (
SecondsTimer в данном случае играет роль presentation компонента, который сам ничего не умеет делать, а просто является шаблоном для отображения своих props в удобном для пользователя виде.
Реализуйте контейнерный компонент, который будет обеспечивать состояние и логику для любого таймера:
TimerContainer должен:
воспринимать три пропса:
seconds - секунды для обратного отсчета
refresh - периодичность обновления таймера в миллисекундах
render - компонент для отрисовки, которому передается текущее время
Время вычисляется не по количеству обновлений, а по разности между стартовым и текущим моментом. Иначе таймер будет очень неточен
так как JSX понимает переменные с маленькой буквы не как компоненты-функции, а как тэги HTML, переприсвойте props render в переменную с большой буквы и используйте её в JSX, как имя компонента, передавая пропс seconds.
Так как при любом обновлении состояния функция-компонент, как и любая другая функция, запускается целиком используйте setInterval в useEffect*/
const SecondsTimer = ({seconds}) =>
{seconds}
function TimerContainer({seconds, refresh, render}) {
const [timeStart, setTimeStart] = useState((new Date()).getTime())
const [timeNow, setTimeNow] = useState((new Date()).getTime())
const [timerIsActiv, settimerActiv] = useState(true)
let time = (seconds - (timeNow - timeStart))/1000
console.log('time' , time)
if (time<0)time=0
useEffect(
()=>{
if (time <= 0){
console.log("time < 0", timeNow)
settimerActiv(false)
setTimeNow(seconds + timeStart)
}
}, [timeNow])
useEffect(
()=>{
if(timerIsActiv) {
const intervalId = setInterval(()=>{
console.log(timeNow)
setTimeNow((new Date()).getTime())
}
, refresh)
return ()=>clearInterval(intervalId)
}
}, [timerIsActiv])
const Render = render
return (
)}
/*LCD
Сделайте из компонента Timer presentation компонент без state, прикрутите его к TimerContainer*/
function TimerPresentation({seconds, timerIsActiv = false, settimerActiv}){
return (
{seconds}
)
}
/*Watch
Реализуйте часы со стрелками в качестве presentation компонента:
квадратный блок-контейнер
стрелки и, возможно, цифры позиционируются с помощью transform: rotate(УГОЛdeg)
В верстке используйте position absolute для накладывания блоков стрелок и цифр друг на друга (это даст общий центр вращения)
для корректного центра вращения блок со стрелкой или цифрой должен быть шириной с родительский квадратный блок
есть еще всякий css (text-orientation) для вращения цифр внутри повернутого блока*/
function Watch({seconds}) {
let hours = seconds / 3600
console.log('hours' , hours)
let hDeg = hours * 30
console.log('hDeg' , hDeg)
let minutes = (seconds % 3600) / 60
console.log('minutes' , minutes)
let mDeg = minutes * 6
let sec = seconds % 60
let sDeg = sec * 6
return (