更新State对象内部的嵌套属性的最佳方法是什么?
// constructor --
this.state.someprop = [{quadrangle: {rectangle: {width: * }}, ...}]
...
我想更新矩形对象的宽度。
this.state.quadrangle.rectangle.width = newvalue // isn't working
我可以让它像:
const {quadrangle} = this.state
quadrangle.rectangle.width = newvalue
this.setState = {
quadrangle: quadrangle
}
但这种方法听起来不是性能/内存的最佳方式
答案 0 :(得分:5)
// ES6 WAYS TO UPDATE STATE
// NOTE: you MUST use this.setState() function for updates your state
class Example extends Component {
constructor(props) {
super(props);
this.state = {
name: 'John',
details: {
age: 28,
height: 1.79,
}
}
componentDidMount() {
this.handleChangeName('Snow');
this.handleAgeChange(30);
}
componentDidUpdate() {
console.log(this.state);
/*
returns
{
name: 'Snow',
details: {
age: 30,
height: 1.79,
}
}
*/
}
// this way you keep immutable your previous state (best practice) with de
// param "prevState"
handleChangeName = (_name) => {
this.setState(
(prevState) => ({
name: _name
})
)
}
//this is how you update just one property from an internal object
handleAgeChange = (_age) => {
this.setState(
(prevState) => ({
details: Object.assign({}, prevState.details, {
age: _age
})
})
)
}
// this is the simple way to set state
handleSimpleAgeChange = (_age) => {
this.setState({
details: Object.assign({}, this.state.details, { age: _age })
})
}
render() {
return (
<h1>My name is {this.state.name} and i'm {this.state.details.age} years old</h1>
)
}
}
如果你想保持最佳练习而不加强,你可以这样做:
updateState = (obj) => {
if (obj instance of Object) {
this.setState(
(prevState) => (Object.assign({}, prevState, obj))
);
}
}
用法:
//code ... code ... code ...
handleAgeChange = (_age) => {
this.updateState({
details: Object.assign({}, this.state.details, { age: _age }
})
}
答案 1 :(得分:4)
最好的方式,以及Facebook提出的方式,是使用'use strict';
// Config
var gulp = require('gulp');
var debug = require('gulp-debug');
var tap = require('gulp-tap');
var exec = require('gulp-exec');
var dest = require('gulp-dest');
var config = {
fluid: {
src: './src/Templates/*.html',
dest: './.build/',
partialRootPaths: './src/Partials/',
layoutRootPaths: './src/Layouts/'
}
};
// Tasks
gulp.task('default', ['build']);
gulp.task('build', ['fluid']);
// Default
gulp.task('fluid', function () {
var options = {
continueOnError: false, // default = false, true means don't emit error event
pipeStdout: true, // default = false, true means stdout is written to file.contents
partialRootPaths: config.fluid.partialRootPaths,
layoutRootPaths: config.fluid.layoutRootPaths
};
// TODO: add JSON variables, if there is a json file with the same name as the template file
// check if file name of template file is readable and writeable, then check if json file exists, then add param to exec function
gulp.src(config.fluid.src)
.pipe(exec(
'fluid --template <%= file.path %> --partialRootPaths <%= options.partialRootPaths %> --layoutRootPaths <%= options.layoutRootPaths %>',
options
))
// .pipe(tap(function (file,t) {
// console.log(file.path);
// }))
.pipe(gulp.dest(config.fluid.dest));
});
。
使用它是唯一可以保证组件正确呈现的方法。
这个函数是增量的,所以你不需要设置整个状态,只需要你需要的道具。
我强烈建议您阅读文档here。
答案 2 :(得分:0)
如果你的对象是嵌套的,那么使内部对象成为它自己的状态,
~
然后使用你的克隆和替换技术:
this.state = {
quadrangle: {this.state.rectangle, ...}
rectangle: {width: * }}
};
国家应该向上传播。如果只需要根据所述矩形更新某些四边形,则应该提高性能。道具失败,陈述。
答案 3 :(得分:0)
带钩子使用这种方式 -setBorder((pre)=> {return({... pre,border_3:2})})
// state for image selected [ borderd ]
const [bordered, setBorder] = useState({ border_1: 0, border_2: 0, border_3: 0, border_4: 0, border_5: 0, border_6: 0, border_7: 0, border_8: 0 });
// pre is previous state value
const handle_chose = (y) => {
//generate Dynamic Key
var key = "border_" + y;
setBorder((pre) => { return ({ ...pre, [key]: 2 }) })
}