zastrzeżenie: Robię pewne założenia w tej odpowiedzi, mimo to świeci światło niektóre z moich (i wcześniej) pytania. Również moje rozwiązanie można prawie na pewno uprościć, ale w celu udzielenia odpowiedzi na to pytanie powinno być ono odpowiednie.
To jest świetne pytanie. Byłem nieco zaskoczony, otwierając narzędzia dla programistów i sprawdzając, co się dzieje podczas zamiany przedmiotów.
Jeśli spojrzysz, możesz sortować Zobacz, co React zamierza. Drugi element w ogóle nie zmienia swojego stylu i po prostu zamienia wewnętrzny węzeł tekstowy, podczas gdy pierwszy element jest upuszczany do dom jako świeży element.
Gdybym musiał zgadnąć, wynika to ze sposobu zamiany dwóch elementów w szyku, w którym co najmniej jeden element jest kopiowany do zmiennej temp i umieszczany z powrotem w tablicy.
Pomyślałem, że może jeśli zrobisz tłumaczenie losowo, oba elementy otrzymają rekwizyty nowego stylu i ożywią, ale to tylko sprawiło, że stało się jasne, że nie było to zamierzone zachowanie.
W drodze do znalezienia rozwiązania:
jako eksperyment, co jeśli stworzyliśmy węzły z wyprzedzeniem, i przekazać wskaźnik prop w renderowania poprzez React.cloneElement
. Podczas gdy jesteśmy na to, w przeciwnym wypadku, wyrenderujmy: span
ifi div
. Bez kluczy do obaw.
http://codepen.io/alex-wilmer/pen/pbaXzQ?editors=1010
Otwarcie narzędzia dev ilustruje teraz dokładnie co React zamierza. React zachowuje elementy i zmienia tylko odpowiednią część, w tym przypadku węzeł innerText i typ elementu. Ponieważ style są zamieniane dokładnie na 1: 1, nie jest wymagana aktualizacja stylu.
Rozwiązanie:
Można wygenerować elementy reagować z wyprzedzeniem, zachować te w tablicy, i jako takie nie istnieją żadne klucze shuffle wokół i dowiedzieć się, jak umieścić z powrotem do DOM. Następnie użyj innej tablicy, aby śledzić zamierzoną kolejność. Prawdopodobnie bardzo zawiłe, ale działa!
http://codepen.io/alex-wilmer/pen/kXZKoN?editors=1010
const Item = function (props) {
return (
<div
style={{position: 'absolute',
transform: `translateY(${props.index * 20}px)`,
transition: '0.5s linear transform'}}>
{props.children}
</div>
)
}
const App = React.createClass({
getInitialState() {
return {
items: [
{item: 'One', C: <Item>One</Item>},
{item: 'Two', C: <Item>Two</Item>}
],
order: ['One', 'Two']
};
},
swap() {
this.setState({
order: [this.state.order[1], this.state.order[0]]
});
},
render: function() {
return <div>
<button onClick={this.swap}>Swap</button>
<div style={{position: 'relative'}}>
{this.state.items.map(x =>
React.cloneElement(x.C, {
index: this.state.order.findIndex(z => z === x.item)
}))
}
</div>
</div>;
}
});
React zachowuje się tak jak powinien, nie ma gwarancji, że element będzie * Pobyt w DOM *, tylko że to będzie zoptymalizować co to da. To, czego potrzebujesz, to React's [ReactCSSTransitionGroup] (https://facebook.github.io/react/docs/animation.html). –
ReactCSSTransitionGroup służy do tworzenia animacji Enter/Leave. Z dokumentacji biblioteki: "[To] ... jest łatwym sposobem na wykonywanie przejść i animacji CSS, gdy komponent React wchodzi na DOM lub z niego wychodzi". Nie jestem pewien, czy jest to przydatne do zmiany kolejności animacji. –
Całkiem dobrze, myślałem, że użyłem go do wcześniejszego zamawiania. Przepraszam za błąd :) –