React Native, construct initial state values from a object or array - arrays

Is it possible to create states in the constructor passed to that component from an array or object.
Here is what is to be achieved:
constructor(props) {
super(props);
this.state= {
Object.keys(this.props.data).map((key, i) => {
[key]: 'boo',
})
}
}
but it returns a syntax error.
The idea is that the data within this.props.data creates a series of states. The data passed to this.props.data is not known by the component in advance but is passed to it as a prop when the component is used.

You could directly declare this.state with return array of map
updated
constructor(props) {
super(props);
this.mapData = Object.keys(this.props.data).map((key, i) =>({[key]: 'boo'}))
this.state = this.pre_state ? Object.assign({}, ...this.pre_state) : {};
}

Related

How to update React component?

I have a child object (element of list) which is rendered inside(?) the parent one. The component has the following properties (from JSON):
contract
{
id,
name,
}
But I need to add another one additional property which is filled in after an HTTP request with an external function to the API (for example, uuid) using one of the existing properties of an object.
My current React code looks the following way (only child component is provided):
class Contract extends Component {
constructor(props){
super(props);
this.state = {data: this.props.contract};
getUuidByName(this.state.data.name).then(val => {
this.state.data.uuid = val;
});
}
componentDidUpdate(){ }
render() {
return <tr>
<td>{this.state.data.id}</td>
<td>{this.state.data.name}</td>
<td>{this.state.data.uuid}</td>
</tr>
}
}
Everything rendered good except an additional property: uuid. Of course I do something wrong or don't do some important thing, but I have no idea what to do.
You are mutating state in the constructor. Never mutate state directly. If you are needing to set/initialize some state after it's been constructed, or mounted, then you should use the componentDidMount lifecycle method. Ensure you enqueue the state update via the this.setState method.
class Contract extends Component {
constructor(props){
super(props);
this.state = {
data: props.contract,
};
}
componentDidMount() {
getUuidByName(this.state.data.name).then(val => {
this.setState(prevState => ({
data: {
...prevState.data,
uuid: val,
},
}));
});
}
componentDidUpdate(){ }
render() {
return (
<tr>
<td>{this.state.data.id}</td>
<td>{this.state.data.name}</td>
<td>{this.state.data.uuid}</td>
</tr>
);
}
}
Do not modify state directly.
Because you're directly modifying the state, React isn't triggering a re-render.
Try the following in your constructor instead:
constructor(props){
super(props);
this.state = {data: this.props.contract};
getUuidByName(this.state.data.name).then(val => {
this.setState({
data: {
...this.state.data,
uuid: val
}
});
});
}

react-native: How to setState() dynamic state in react-native?

I can create dynamic state like this example:
constructor(props) {
super(props);
this.state = {};
}
create state with this method:
func(name){
this.state[name];
}
and setState with this:
func2(name,value){
this.setState({[name]:value});
}
so with
this.func('color');
this.func('size');
I have this.func.color and this.func.size. right?
It works.
But I want something like this. I want create all new dynamic state in 'names' state.
constructor(props) {
super(props);
this.state = {names:[]};
}
names is a normal state.
func(name){
this.state.names[name];
}
func2(name,value){
this.setState({names:{[name]:value}:});
}
I call this functions:
func('color');
func('size');
func2('color','red');
func2('size','larg');
I expect with console.log(this.state.names) this:
{color:'red',size:'larg'}
But I get only {size:'larg'} (second function)
what is my wrong?
You're overwriting the value of names when you call this.setState again.
You're effectively doing:
this.setState({ names: { color: 'red' }});
this.setState({ names: { size: 'large' }});
Consider using Object.assign() in func2 to make sure you're not replacing the object you're trying to add properties to.
func2(name,value) {
this.setState({
names: Object.assign(this.state.names, {[name]: value})
});
}

React add unmounted component to the array

Im trying to create multiple components for future rendering adding tham to the array like this:
widgets.push(<TextWidget fieldData={fieldData} correctionFactor={correctionFactor} />);
but in my component I'm getting
TypeError: Cannot set property 'FieldData' of undefined
class TextWidget extends Component {
FieldData = null;
CorrectionFactor = null;
state = {
FieldData: null,
CorrectionFactor: null
}
constructor(props) {
this.FieldData = props.fieldData;
this.CorrectionFactor = props.correctionFactor || 1;
}
componentDidMount() {
this.state.FieldData = this.FieldData;
this.state.CorrectionFactor = this.CorrectionFactor;
}
....
if i do smth like this.state.FieldData = props.FieldData; in a constructor then react is complaining about being unable to set state of unmounted component.
I think that you forgot call super() inside your constructor as a first line
super(props);
According to the React docs:
You should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
You're committing two mistakes.
First: You should call the super(props) before manipulating the props, then use the this.props.FieldData, and you could do it even in the constructor(), when defining the state, like:
constructor(props) {
super(props);
this.state = {
FieldData: this.props.FieldData,
CorrectionFactor: this.props.CorrectionFactor || 1
};
}
Second: You shouldn't set state like you did:
this.state.FieldData = this.FieldData;
You should use the this.setState()(read the docs), like below:
this.setState({
FieldData: this.props.FieldData,
CorrectionFactor: this.props.CorrectionFactor
});

How can I set up state in a React app using arrays in a json object as well as arrays not in the json object?

I have a json object which I have set the state of my app to
class App extends Component {
constructor (props) {
super(props)
this.state = DATA;
}
The json object has a an array of product objects.
I would also like to add an empty array to the state.
This array with have products pushed into it when the user clicks on the product.
This array doesn't exist in the json object.
How can I set this up as this.state = DATA;
React state accepts the objects. So if you wanna initialize your state with an empty array, you can assign like this
class App extends Component {
constructor (props) {
super(props)
this.state = {
data : blahblahblah,
products : []
}
}
}
And For example, when you wanna access the product array , you can update using
this.setState({products : [id:'1', product_name : 'something']})
You can intialise the state in your constructor as,
constructor (props) {
super(props)
this.state = {
data:DATA,
products:[]
}
}
And when your select a product you will have to push new items into product array like,
addProduct(item){
let products=[...this.state.products];
prosucts.push(item);
tis.setState({products:products});
}

Is Initializing state with props object causes mutation?

In my React application, one of the components needs state initialization from props.
Class ComponentA extends React.Component{
constructor(props){
this.state = {
objectA: props.objectA
}
}
someOnclickFunction(e){
let updatedObjA = this.state.objectA;
updatedObjA.value = e.target.value;
this.setState({
objectA: updatedObjA
})
}
}
In the above code snippet, props.objectA reference is copied to state. So, Am I mutating the props indirectly by updating the state?
Or setState() function will clone the object and keep new reference for the objectA?
class ComponentA extends React.Component {
constructor(props) {
super(props);
// state is null at this point, so you can't do the below.
// this.state.objectA = props.objectA
// instead, initialize the state like this:
this.state = {
objectA: props.objectA,
};
}
someOnclickFunction(e) {
// you can't set "objectA.value" like the following
// this.setState({
// objectA.value: e.target.value
// });
// you need to create a new object with your property changed, like this:
this.setState({
objectA: Object.assign({}, this.state.objectA, { value: e.target.value }),
})
}
}
This is a mistake that many beginners at react make. You can't simply update sub-properties of an object without consequences.. The following would also be wrong:
someOnclickFunction(e) {
var tmp = this.state.objectA;
// WRONG: don't do this either, you're modifying the state by doing this.
tmp.value = e.target.value;
this.setState({
objectA: tmp,
});
}
To elaborate on the correct way to do this using Object.assign.. this function takes all the parameters and merges them into the first element. So by providing a new object as the first parameter, you've created a copy of your first object with your new property.
Object.assign({}) // = {}
Object.assign({}, objectA) // = copy of objectA
Object.assign({}, objectA, { value: "newValue" }) // = copy of objectA with 'value' = 'newValue'.
Note: Object.assign() is a shallow clone, not a deep clone.

Resources