今天遇到的问题是:组件内对数组元素进行修改后数据有变化但是页面没重新渲染
话说这是因为组件没能够识别数组的变化,所以页面没有重新渲染
所以只要让组件感知到你发生了改变,就可以达到刷新的效果
import React, { Component } from 'react';
import './App.css';
import Todo from './components/todo/index'
import { Table, Button } from 'element-react';
class App extends Component {
constructor(props) {
super(props);
this.state = [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
},{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
render() {
return (
<div>
<Todo list={this.state.data}/>
<Table
style={{width: '100%'}}
columns={this.state.columns}
data={this.state.data}
/>
<Button type="primary" onClick={this.addData.bind(this)}>添加</Button>
</div>
);
}
addData () {
let obj = {
date: '2018-05-07',
name: '小明',
address: ''
};
let data = this.state.data;
data.push(obj);
this.setState({
data: data
});
console.log(this.state);
}
}
export default App;
上面代码中 通过setState设置data的值发现视图并没有更新,原因是数组的赋值是引用传递的,data = this.state.data其实是将this.state.data的内存地址复制给了data,所以执行data.push(obj)实际上相当于执行了 this.state.data.push(obj),因为地址指向一个地方,所以react的虚拟dom发现state里面的data没有变化,所以不更新视图,而这时可以使用一个新数组:
let data = [...this.state.data];
同理,React Hook也会发生上述问题
import React, { useState, useEffect } from "react";
import TestItem from "../TestItem/TestItem.js";
import Count from "../count";
const _ = {
map: require("lodash/map"),
fill: require("lodash/fill"),
set: require("lodash/set")
};
const Main = () => {
const [name, setName] = useState("");
const [count, setCount] = useState(0);
const [datas, setDatas] = useState([]);
const getDatas = () => {
setDatas([
{ title: "分类一", index: 0 },
{ title: "分类二", index: 1 },
{ title: "分类三", index: 2 }
]);
};
useEffect(() => {
setName("hello world");
getDatas();
}, []);
useEffect(() => {
console.log("data has changed !!!!!");
}, [datas]);
const onClick = index => {
const result = _.set(datas, [index, "title"], "哎呀我去");
// ❌错误的方式
// setDatas(result)
// 方法一
// setDatas(JSON.parse(JSON.stringify(result)));
// 方法二
// setDatas([...result]);
// 方法三
let tmp = [...datas]; // 切不可 let tmp = datas
tmp[index].title = "哈哈哈哈";
setDatas(tmp);
// 方法四
//使用lodash的_.cloneDeep()
};
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<div>
{datas.map((item, index) => {
return <TestItem data={item} key={index} onClick={onClick} />;
})}
</div>
<div>
<Count count={count} handleClick={handleClick} />
</div>
</div>
);
};
export default Main;
涉及到的知识点是对象的深拷贝与浅拷贝,这里有一篇关于深拷贝与浅拷贝的文章很好,感兴趣的童鞋可以看一下哦~~js浅拷贝与深拷贝的区别和实现方式