我使用CSS过渡编写了一个React应用程序。但是这些转换在某些组件中无法正常工作。在my app中,只有向上移动的组件才能正常运行,向下移动的组件会在没有动画的情况下立即移动。 (我希望它们都带动画。)
这是我在那里使用的CSS:
componentDidUpdate
更新:
我还构建了一个codepen.io project来显示问题。它有完整的演示项目代码。
我尝试向componentDidMount
,componentWillUnmount
和my $qstr = "select $subject.id as id, $subject.status as status, $subject.title as title, $subject.component as component, $subject.submitted_date as submitted_date, $subject.closed_date as closed_date from $subject where ($subject.title = 'PM_Production' and ($subject.status = 'complete' OR $subject.status = 'rejected'))";
方法添加日志条目,以显示是否重新创建或更新了这些组件,它表明它们都已更新(不是每次重新创建或删除)。
答案 0 :(得分:19)
好吧,在我开始赏金之后因为我也遇到了这个问题,我终于找到了什么似乎是问题。
当你使用绝对位置(或相对的,如你的情况)时,如果你每次重新渲染整个列表,React将重新排序DOM中的元素(如你所说,元素不是重新创建,刚更新)。但这会产生转换的问题......显然,如果在转换运行时移动元素,那么最终会切割动画。
因此,对于你想要使用绝对位置的情况,关键的概念是渲染元素的容器一次(在这种情况下,只是div),并且只根据新的顺序更改内部内容。如果您需要添加更多元素,请在最后添加它们。
我修改了你的codepen,以便反映我所说的内容。我的例子非常愚蠢,因为我刚刚创建了4个ad-hoc div,但它说明了这个想法:根据需要创建尽可能多的容器,但不要使用每次都重新创建它们的地图,否则你的过渡将被切断。
https://codepen.io/damianmr/pen/boEmmy?editors=0110
const ArrList = ({
arr
}) => {
return (
<div style={{position: 'relative'}}>
<div className={`element element-${arr[0]} index-${arr[0]}`}>{arr[0]}</div>
<div className={`element element-${arr[1]} index-${arr[1]}`}>{arr[1]}</div>
<div className={`element element-${arr[2]} index-${arr[2]}`}>{arr[2]}</div>
<div className={`element element-${arr[3]} index-${arr[3]}`}>{arr[3]}</div>
</div>
);
}
因此,问题基本上是如何创建静态容器列表以及如何遍历该列表,以便第一个容器呈现数据的第一个元素,第二个容器呈现第二个元素等等。
希望它有所帮助,这个问题也让我发疯了! :)
答案 1 :(得分:2)
如果要从虚拟DOM中删除元素,则react会更新其内容,因此您将看不到动画。您可以做的是使用react-transition-group或者告诉您的应用在调用事件后更新dom之前等待x ms或使用可见性在隐藏和显示之间切换,而不是从DOM中完全删除它。
答案 2 :(得分:2)
您可以使用index
作为密钥欺骗React。如果您将el
和index
视为起始位置(索引)和结束位置(el),则该元素在转换结束时已移至旧的结束位置,并且当它在那里时,它被新的起始位置接管,并且(索引)被切换以匹配新的设置。这是因为当您在react中的元素中设置key
时,虚拟DOM将始终将其解释为同一元素。并且为了它,你通常将索引设置为“id”。
我只通过切换index / el(并将元素位置设置为绝对值)来创建一个工作示例。
const {combineReducers, createStore} = Redux;
const { Provider, connect } = ReactRedux;
const ArrList = ({
arr
}) => (
<div>{
arr.map((el, index)=>
<div
key={""+index}
className={`element element-${el}` + ` index-${el}`}
>
{el}
</div>) }
</div>
)
const mapStateToArrList = (state) => {
return {
arr: state.appReducer.arr
}
};
const App = connect(mapStateToArrList, null)(ArrList);
const initialState = {
arr: [1, 2, 3, 4]
}
const appReducer = (state = initialState, action) => {
switch(action.type) {
case "tick":
return {
...state,
arr: _.shuffle(state.arr)
}
default:
return state
}
}
const reducer = combineReducers({
appReducer
})
const store = createStore(reducer)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
const dispatcher = () => {
store.dispatch({
type: "tick"
})
setTimeout(dispatcher, 1000)
}
dispatcher()
.element {
position: absolute;
height: 20px;
background: green;
margin-left: 20px;
margin-top: 20px;
text-align: right;
color: white;
line-height: 20px;
transition: all 1s ease-in;
-moz-transition: all 1s ease-in; /* Firefox 4 */
-webkit-transition: all 1s ease-in; /* Safari 和 Chrome */
-o-transition: all 1s ease-in; /* Opera */
}
.element-1 {
width: 20px;
}
.element-2 {
width: 40px;
}
.element-3 {
width: 60px;
}
.element-4 {
width: 80px;
}
.index-1 {
top: 20px;
}
.index-2 {
top: 40px;
}
.index-3 {
top: 60px;
}
.index-4 {
top: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script>
<div id="root"></div>
答案 3 :(得分:2)
我知道不是这种情况,但是由于我到这里也是在寻找React css transition does not work correctly
,所以我只想分享一下:
如果您使用render
中的箭头功能创建一个元素,则该元素将无法正确显示动画,因为始终会创建一个新的组件。
您应该在外部创建一个函数,然后在“渲染”中调用它。
答案 4 :(得分:1)
您每次都重新创建DOM
个元素
您应该定义collect键值。
我将键值'' + el
更改为'' + index
。
<div key={'' + index} className={'element element-' + el + ' index-' + index} >
只需更改css
属性:)