在本地更新/更改状态对象的最佳方法是什么?

时间:2016-12-12 12:24:46

标签: javascript reactjs react-native

更新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
}

但这种方法听起来不是性能/内存的最佳方式

4 个答案:

答案 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 }) })

 }