I have the code:
constructor(props){
super(props);
var ds= new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
var messagesArray = [
{message: "Hello", style: styles.nikkiMes},
{message: "Okkkk", style: styles.userMes}
];
this.state = {
messagesSource: ds.cloneWithRows(messagesArray.slice());
};
}
Error in the line:
messagesSource: ds.cloneWithRows(messagesArray.slice());
Why i cannot to pass array into cloneWithRows?
You shouldn't put a semicolon in your object definition. Different properties are seperated by commas, not semicolons.
e.g.
obj = {
var: 'myVar',
anotherVar: 'myVar2',
}
So this:
this.state = {
messagesSource: ds.cloneWithRows(messagesArray.slice());
}
Should be
this.state = {
messagesSource: ds.cloneWithRows(messagesArray.slice())
}
you just add a terminator ";" in line
messagesSource: ds.cloneWithRows(messagesArray.slice())
just remove this and your code is work perfectly.
var messagesArray =[{message:"data1"},{message:"data2"},{message:"data3"}];
this.state = {
messagesSource: ds.cloneWithRows(messagesArray.slice())
}
Related
I have a table component that I am using to display the information from all other components in my app. This means that when I send data I can't use the following:
db.collection(collectionName).add({
key1: val1,
key2: val2,
etc...
})
Because the keys could be different depending on which component is using table. I've thought about doing this with a .map() or forEach going through each key but I keep getting syntax errors.
I originally assumed that I could just send the object new_row but that doesn't seem to work properly.
Here is my table component:
class Table extends Component {
constructor(props){
super(props);
this.state = {
rows: null,
temprows: null,
newrow: null,
parent: this.props.tableComponent
}
}
addRow = function(){
var new_rows = [...this.state.rows];
new_rows.push(this.state.newrow);
var new_row = JSON.parse(JSON.stringify(new_rows[0]));
Object.keys(new_row).forEach(function(index) {
new_row[index] = '';
});
db.collection(collectionNAame).add({
I want to add the data here
})
this.setState({
rows: new_rows,
newrow: new_row
});
}
Is there also a better approach, some other method aside from .add for this specific case?
In db.collection .add method, spread and pass this.state.newrow and in the then block update your state. Also in your addRow function, the new_row should be obtained from state (not new_rows[0]
Like this
class Table extends Component {
constructor(props) {
super(props);
this.state = {
rows: null,
temprows: null,
newrow: {},
parent: this.props.tableComponent
};
}
addRow = function() {
var new_rows = [...this.state.rows];
new_rows.push(this.state.newrow);
// var new_row = JSON.parse(JSON.stringify(new_rows[0]));
var new_row = { ...this.state.newrow };
db.collection(collectionNAame)
.add({
...this.state.new_row
})
.then(() => {
Object.keys(new_row).forEach(function(index) {
new_row[index] = "";
});
this.setState({
rows: new_rows,
newrow: new_row
});
});
};
}
There is a state and i want to update this state with in a function.
In function i declared a variable and i want to update state with this variable.
this.state = {
RequestData : [],
searchopen : false,
capturedImage : ""
}
screenShot = () => {
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
});
this.setState({capturedImage: base64URL})
}
You need to put setState in function that get base64URL and bind your screenShot function to use this.setState:
// constructor
constructor(props) {
super(props);
this.state = {
RequestData: [],
searchopen: false,
capturedImage: ""
}
this.screenShot = this.screenShot.bind(this);
}
screenShot = () => {
html2canvas(document.body).then(function (canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
this.setState({ capturedImage: base64URL })
}.bind(this)); // bind here also
}
The problem here is you are doing the state update outside the callback function. Since this is a asynchronous task, your method will not work. Try this:
screenShot = () => {
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
this.setState({capturedImage: base64URL})
});
}
Not pretty but should work
this.state = {
RequestData : [],
searchopen : false,
capturedImage : ""
}
screenShot = () => {
var setState = newStore => this.setState((state, props) => ({ ...newStore })); // define the function outside
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg','image/octet-stream');
setState({capturedImage: base64URL}) // use here
});
}
In my state, I want to update an object property on the first item in an array of objects. The object property isn't changing, even though I am taking steps to ensure immutability.
this.state = {
myFruits: [{a: false, b: 2, c: 'apple'}, {'a': false, b: 4, c: 'kiwi'}, ...],
otherCategory: {}
}
/// further down the code in componentDidUpdate
{ myFruits } = this.state;
let copyFruits = [...myFruits];
let newFruit = { ...copyFruits[0], a : true };
// console.log(newFruit): {a: true, b: 2, c: 'apple'}
copyFruits[0] = newFruit;
// console.log(copyFruits[0)] = {a: true, b: 2, c: 'apple'}
this.setState({ myFruits: copyFruits });
// the end result is the same as the original state, where the first item, apple, has a : false instead of expected a : true
This change is being made in componentDidUpdate, and I'm not sure if this has any effect.
I guess the problem is that your componetDidUpdate method is not getting called.
The code you have written here is perfectly fine.
class SolutionExample extends React.Component {
constructor(){
super()
this.state = {
myFruits: [{a: false, b: 2, c: 'apple'}, {'a': true, b: 4, c: 'kiwi'}],
otherCategory: {}
}
}
changeKey =() =>{
let { myFruits } = this.state;
let copyFruits = [...myFruits]
let newFruit = { ...copyFruits[0], a : true };
copyFruits[0] = newFruit;
this.setState({ myFruits: copyFruits });
}
componentDidUpdate()
{
// this method is called whenever the state is changed }
render() {
let { myFruits } = this.state;
return (
<div>
<h1>Solution</h1>
{myFruits.map((item) =>{
if(item.a){
return(<h2>{item.b + '-' + item.c}</h2>)
}
})}
<button onClick={this.changeKey}>Change state</button>
</div>
);
}
}
ReactDOM.render(<SolutionExample />, document.getElementById('example'));
Here is the link : https://codepen.io/anon/pen/pXYdWQ
You can simplify your change to:
const { myFruits } = this.state;
let newFruit = { ...myFruits[0], a : true };
this.setState({ myFruits: [newFruit, ...myFruits.splice(1)] });
Also, a better approach is to map and update the object that you need by an id or any unique identifier.
this.setState({
myFruits: myFruits.map(fruit => {
if(fruit.c === "apple") {
fruit.a = true
return fruit;
}
return fruit;
})
})
I am new to React, so I know I might not be doing everything right.
I am trying to call setStatus inside of a callback for onreadystatechange but getting an error in the browser. The code does an AJAX call to the server to see if a proposed username is already in the database. Upon return the onreadystatechange is executed. There I am trying to set the new error message for the username if it already exists.
Here is my state data:
const initialState = {
firstname: "",
lastname: "",
username: "",
password: "",
email: "",
firstnameError: "",
lastnameError: "",
usernameError: "",
passwordError: "",
emailError: ""
};
class SignUpForm extends Component {
constructor() {
super();
this.state = initialState;
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.checkUserName = this.checkUserName.bind(this);
this.checkEmail = this.checkEmail.bind(this);
this.validateForm = this.validateForm.bind(this);
}
This is where I update state in a change handler for fields in the form:
handleChange(e) {
let target = e.target;
let value = target.value;
let name = target.name;
if (name === "username") {
value = value.toUpperCase();
}
this.setState({
[name]: value
});
}
This is the routine where I am getting an error in the browser. The lines where the error occurs is marked with a comment on the line below.
checkUserName() {
let usernameError = "";
let element = "";
let checkNameResponse = "";
let checkNameMessage = "";
let request = "";
let url = "";
let userName = "";
let requestData = "";
let checkNameResponseJSON = "";
request = new XMLHttpRequest();
if (request == null) alert("Unable to create checkDBForUSerNameRequest");
else {
url = "/php/CheckUsername.php";
userName = escape(document.getElementById("username").value);
requestData = JSON.stringify({
username: userName
});
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
checkNameResponseJSON = JSON.parse(request.responseText);
checkNameResponse = checkNameResponseJSON.returncode;
checkNameMessage = checkNameResponseJSON.message;
element = document.getElementById("SignupIcon");
element.className = "displayIcon";
if (checkNameResponse === 0) {
element = document.getElementById("SignupIconFile");
element.src = "/images/YesButton.png";
element.alt = "Available";
this.setState({ usernameError: "" });
} else {
element = document.getElementById("SignupIconFile");
element.src = "/images/NoButton.png";
element.alt = "Not Available";
usernameError = checkNameMessage;
this.setState({ usernameError: usernameError }); // BROWSER ERROR
}
}
};
request.open("POST", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.send(requestData);
}
}
This is the text from the browser error:
0: Object doesn't support property or method 'setState'
Any ideas why this happens or how to fix?
The error is because you are using request.onreadystatechange = function() {} instead of request.onreadystatechange = () => {} or request.onreadystatechange = function() {}.bind(this)
When you use function(), the scope of this changes.
Remember that function() {} and () => {} are not the same.
but function(){}.bind(this) and () => {} are the same.
You need to bind the onreadystatechange function using .bind or arrow function since when the function is executed it needs to access the correct this value referring to the class context.
request.onreadystatechange = function() {
// all logic here
}.bind(this)
or
request.onreadystatechange = () => {
//all logic here
}
i want to fill a picker items from array .. this array store data from local storage and i want to display this data on picker
this is my function that retrieve data from local storage
async getElementsInLocalStorage() {
try{
let x = [];
let all_keys = await AsyncStorage.getAllKeys();
for(i = 1; i <= all_keys.length;i++ ){
let converter = JSON.parse(await AsyncStorage.getItem('one_person'+i));
x[i] = converter.first_name + ' ' + converter.last_name;
}
this.setState({all_options: x, data: x,});
} catch(error){
alert(error)
}
}
And this is my constructor
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
};
data = [];
}
And this is my Picker
<Picker selectedValue = {this.state.selected} >
{this.state.data.map((value)=><Picker.Item label={value} value={value}/>)}
</Picker>
when type data only in picker picker not filled but when type this.state.data
this is error return
You have defined data as a seperate variable in constructor. But after fetching data you are considering data as a state variable.
Just declare data inside state, and that might solve your issue.
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
data:[]
};
}
Can you try this. What I did is
Moved data inside state and added conditional check before doing .map
constructor(){
super();
this.state = {
first_name: '',
last_name : '',
all_options : [],
data = []
};
}
And this is my Picker
<Picker selectedValue = {this.state.selected} >
{this.state.data && this.state.data.map(value=> (<Picker.Item label={value} value={value}/>))}
</Picker>