В этом примере кода выходной переход работает, а входной переход - нет. Мне любопытно, если я подхожу к этому правильно, если это ошибка с styled-компонентами.
Цель состоит в том, чтобы анимировать до 50% от экрана при выходе и анимировать от 100% до экрана при вводе. Я установил непрозрачность на 50%, чтобы можно было постоянно видеть оба элемента div.
Я бы предпочел использовать Transition вместо CSSTransition, поскольку я хотел бы просто использовать стилевые компоненты вместо смешивания в обычных таблицах стилей.
Пример кода: https://codesandbox.io/s/sweet-mcnulty-dbptv
Состояния анимации при выходе (см. Консоль в CodeSandbox):
- введено - установить начальное положение и отключить переходы
- выход - установить целевую позицию и разрешить переходы
- выход - не имеет значения, поскольку компонент отключен с помощью реакции-маршрутизатора
ПРИМЕЧАНИЕ: это (выходной переход) работает хорошо.
Состояния анимации при входе (см. Консоль в CodeSandbox):
- выход - установить исходное положение и отключить переходы
- ввод - установить целевую позицию и разрешить переходы
- 1029 * вошел *
Это (входной переход) вообще не анимируется. Большая разница между входом и выходом состоит в том, что при выходе компонент уже смонтирован, а на входе он смонтирован непосредственно перед тем, как должна произойти анимация. Мой рабочий тезис заключается в том, что styled-component не передает оба обновления CSS (шаг 1 и 2) в DOM по отдельности, и поэтому браузер не запускает переход. Но я этого не знаю, во всяком случае, это происходит только в том случае, если вы монтируете перед самым переходом.
Есть идеи?
Пример полного кода (аналогично https://codesandbox.io/s/sweet-mcnulty-dbptv):
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";
import { TransitionGroup, Transition } from "react-transition-group";
const Nav = styled.nav`
display: flex;
justify-content: space-around;
align-items: center;
height: 80px;
`;
const Page = styled.div`
background: white;
display: flex;
justify-content: center;
align-items: center;
will-change: transform;
position: fixed;
top: 80px;
bottom: 0;
left: 0;
right: 0;
background: ${props => (props.backgroundColor === "gray" ? "#eee" : "#efe")};
opacity: 0.5;
transform: ${props => {
// Details page is green
if (props.backgroundColor === "green") {
// console.log(new Date().getTime(), 'Details page (css): ', props.transitionState);
}
switch (props.transitionState) {
case "entering":
return "translateX(0)";
case "entered":
return "translateX(0)";
case "exiting":
return "translateX(-50%)";
case "exited":
return "translateX(100%)";
default:
throw new Error("This should never happen");
}
}};
transition: ${props => {
switch (props.transitionState) {
case "entering":
return "transform 1000ms cubic-bezier(0, 0, 0, 1)";
case "entered":
return "none";
case "exiting":
return "transform 1000ms cubic-bezier(0, 0, 0, 1)";
case "exited":
return "none";
default:
throw new Error("This should never happen");
}
}};
`;
const HomePage = props => {
return (
<Page backgroundColor="gray" transitionState={props.transitionState}>
Home page!
</Page>
);
};
const DetailsPage = props => {
console.log(new Date().getTime(), 'Details page (component):', props.transitionState);
return (
<Page backgroundColor="green" transitionState={props.transitionState}>
Details page!
</Page>
);
};
function App() {
return (
<Router>
<Nav>
<Link to="/">Home</Link>
<Link to="/details">Details</Link>
</Nav>
<Route
render={({ location }) => {
return (
<TransitionGroup component={null}>
<Transition key={location.pathname} timeout={1000}>
{transitionState => {
return (
<Switch location={location}>
<Route
exact
path="/"
render={() => (
<HomePage transitionState={transitionState} />
)}
/>
<Route
exact
path="/details"
render={() => (
<DetailsPage transitionState={transitionState} />
)}
/>
</Switch>
);
}}
</Transition>
</TransitionGroup>
);
}}
/>
</Router>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);