我正在尝试使用React Native ListView
动画交换两行这是我的数据源代码(在我的渲染方法中):
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1.id !== r2.id})
var dataSource = ds.cloneWithRows(state.todoLists[this.props.index].todos.slice())
这是我的交换代码(使用MobX):
var {todo, i} = forID(state.todoLists[list].todos, id) //Gets index and todo from id
state.todoLists[list].todos.splice(i, 1)
state.todoLists[list].todos.push({...todo, done: !todo.done})
正如您所看到的,等式是持久的,因为数组项目只是向下移动。
如果我尝试LayoutAnimation,我会觉得这很奇怪:
有什么想法吗?
答案 0 :(得分:1)
我怀疑问题在于(根据您的说法)您在render
方法中创建了DataSource。您应该在构造函数(或ListView.DataSource
)中创建componentWillMount
对象,然后在数据更改时调用cloneWithRows
,而不是render
。问题是,通过在每个渲染上重新创建一个新的DataSource,它永远不会调用rowHasChanged
函数,因为数据源中从未有过先前的状态。
示例正确实施
在下面的示例中,我在构造函数中设置数据源并将其存储在状态中。然后一旦安装,我就加载todos,并在状态下更新数据源,这将触发重新渲染。
然后,当你想将todo移动到底部时,你会调用this.moveItemToBottom(id)
来修改状态,并更新状态的数据源,并在设置LayoutAnimation后重新渲染。
class TodoList extends Component {
constructor(props, context) {
super(props, context);
this.state = {
ds: new ListView.DataSource({
rowHasChanged: (r1, r2) => (r1 !== r2),
}),
};
}
componentDidMount() {
loadInitialData();
}
loadInitialData() {
// Do something to get the initial list data
let todos = someFuncThatLoadsTodos();
this.setState({
ds: this.state.ds.cloneWithRows(todos),
});
}
moveItemToBottom(id) {
// get your state somewhere??
let todos = state.todoLists[list].todos;
let {todo, i} = forID(state.todoLists[list].todos, id)
todos.splice(i, 1).push({...todo, done: !todo.done});
LayoutAnimation.easeInEaseOut();
this.setState({
ds: this.state.ds.cloneWithRows(todos),
});
}
render() {
return (
<ListView
dataSource={this.ds}
// Other props
/>
);
}
}
&#13;
编辑/注意:我的例子没有考虑与MobX有关的任何事情。我还没有使用它,但是从粗略的看,你可能需要观察todos列表并在它更新时更新数据源,并且让moveItemToBottom
方法更新MobX状态并依赖于observable使用克隆的数据源到setState
。