Как отображать и анимировать компонент React в зависимости от результата условия с помощью React Spring? - PullRequest
0 голосов
/ 06 августа 2020

Я борюсь с рендерингом компонента React в зависимости от результата условия. Чтобы быть более точным, я работаю над приложением «Будильник», где вы можете установить время, когда будильник должен «звонить».

Есть 3 функции, которые обновляются каждую секунду через useEffect () .

  1. currentTime () - получает текущее время и вставляет в состояние

    function currentTime(){
     let time = new Date().toLocaleTimeString('it-IT');
     let hours = time.substr(0,2);
     let minutes = time.substr(3,2);
     let seconds = time.substring(time.length-2)
    
     setTime(prevState => ({
     ...prevState,
     currentHour:hours,
     currentMinute:minutes,
     currentSecond:seconds
     }))
    }
    
  2. currentDate () - получает текущую дату и вставляет в состояние

    function currentDate(){
     let date = new Date();
     let day = days[date.getDay()];
    
     setTime(prevState => ({
     ...prevState,
     currentDay:day
     }))
    }
    
  3. checkTime () - проверяет, если состояние alarmHours пустое или нет. Это состояние имеет значение, только если установлена ​​тревога.

    function checkTime(){
     if(time.alarmHours && time.alarmMinutes){
      if(time.currentHour === time.alarmHours && time.currentMinute === time.alarmMinutes && 
      time.currentSecond === '00'){
        setShowRing(true);
       }
      }
     }
    

Чтобы установить тревогу, вам нужно нажать на кнопку SET ALARM , которая пока находится в правом верхнем углу. После щелчка появляется компонент Alarm. js, который исчезает, а когда вы закончите, исчезает. Эти переходы выполняются с использованием React Spring Transitions.

В этот Alarm. js компонент передается функция как опора из App. js . Эта функция должна получать всю заполненную информацию из Alarm. js (сообщение для будильника и время, когда должен прозвучать сигнал) и сохранять их в состоянии.

function getAlarm(){
 let description = document.getElementById('text').value;
 let hours = document.getElementById('hours').value;
 let minutes = document.getElementById('minutes').value;

 setTime(prevState => ({
    ...prevState,
    message:description,
    alarmHours:hours,
    alarmMinutes:minutes,
 }));
}

In В моем предыдущем вопросе я спрашивал, как вызвать этот компонент Ring, когда условие выполнено, и текущее время равно установленному времени. Мне сказали сделать это:

const [showRing,setShowRing] = useState(false);

Затем при выполнении условия checkTime

setShowRing(true);

И в приложении. js рендеринг:

{showRing && <Ring message={time.message} turnOff={()=>setShowRing(false)} />}

Это работает. Но без переходов и было бы лучше, если бы он был полностью отделен в собственном файле, как Alarm. js. Я пытался добавить к нему переходы, но потом он даже не отображался. Лучшим вариантом будет назвать его как Alarm. js в условии, и все эти переходы будут выполняться в собственном файле. Я имею в виду

function checkTime(){
  if(time.alarmHours && time.alarmMinutes){
   if(time.currentHour === time.alarmHours && time.currentMinute === time.alarmMinutes && 
   time.currentSecond === '00'){
    return <Ring />
  }
 }
}

Но это не работает. Даже если я попытаюсь добавить к нему эти переходы в Ring. js. Кто-нибудь может мне с этим помочь, пожалуйста? Я был бы очень признателен.

CODESANDBOX здесь .

1 Ответ

1 голос
/ 06 августа 2020

Здесь вы немного запутались, потому что если вы визуализируете компонент условно в App, переходу перехода в Ring не будет достаточно времени для завершения, когда компонент будет размонтирован. Либо переход logi c должен находиться в App, либо вы должны постоянно отображать Ring, как вы уже делаете с Alarm. Он также должен быть привязан к состоянию showRing через props - он не может управлять своим собственным состоянием, потому что зависит от родителя.

Я бы предложил постоянно отображать компонент Ring следующим образом:

<Ring message={time.message} showRing={showRing} turnOff={() => setShowRing(false)} />

А внутри:

function Ring(props) {
  const { message, turnOff, showRing } = props;
  const ringTransitions = useTransition(showRing, null, {
    from: { position: "absolute", opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  });

  return (
    <div>
      {ringTransitions.map(
        ({ item, key, props }) =>
          item && (
            <animated.div key={key} style={props} className="overlay">
              <div className="inputBox">
                <h3>{message}</h3>
                <a onClick={turnOff}>TURN OFF</a>
              </div>
            </animated.div>
          )
      )}
    </div>
  );
}
...