For react, is it possible to change the cell color for a component? I know it is way super easy can be done in Jquery by looking at the id/class of the element and do an addClass, but how to do it on react? I'm still figuring it out the changes, what i can think of is that i set the value on a state, but how i get the affected cell and implement the state? Any idea? Or is there any better grid that I can achieve like what can be done in Jquery?
constructor(props, context) {
super(props, context);
this.state = {
cellUpdateCss: ""
};
}
handleGridRowsUpdated = ({ cellKey, fromRow, toRow, updated, action, originRow }) => {
let rows = this.state.rows.slice();
for (let i = fromRow; i <= toRow; i++) {
let rowToUpdate = rows[i];
let updatedRow = update(rowToUpdate, { $merge: updated });
rows[i] = updatedRow;
this.postToServer(updatedRow.data, JSON.stringify(updated));
}
this.setState({ rows });
};
postToServer = (aX, vC) => {
var self = this;
axios.post(this.props.postApi, {
axNo: aX,
updated: vC
})
.then((response) => {
console.log(response);
self.setState({ cellUpdateCss: "green" });
})
.catch((error) => {
console.log(error);
self.setState({ cellUpdateCss: "red" });
});
}
render() {
return (
<ReactDataGrid
onGridRowsUpdated={this.handleGridRowsUpdated}
/>
)
}
third party grid that I use
https://github.com/adazzle/react-data-grid
You can accomplish that by applying the style to the row class name, first of all, in handleGridRowsUpdated function you need to set fromRow, toRow to the constructor state then we need to call the changeStyle function that I did with the callback of setState.
handleGridRowsUpdated = ({ cellKey, fromRow, toRow, updated, action, originRow }) => {
let rows = this.state.rows.slice();
for (let i = fromRow; i <= toRow; i++) {
let rowToUpdate = rows[i];
let updatedRow = update(rowToUpdate, { $merge: updated });
rows[i] = updatedRow;
this.postToServer(updatedRow.data, JSON.stringify(updated));
}
this.setState({ rows, fromRow: fromRow, toRow: toRow },()=>{
this.changeStyle();
});
};
changeStyle function, it will change the color of the edited row.
changeStyle = () => {
var all = document.getElementsByClassName('react-grid-Row');
for (var i = this.state.fromRow; i <= this.state.toRow; i++) {
all[i].style.color = this.state.cellUpdateCss;
}
}
I did a full example on CodeSandbox
Related
Here I'm trying to select multiple files and upload them at one click.When I select single file and upload then it render correctly. But when I upload more than one file ,the last one is not displaying.But it gets stored in the array.It's like always on step behind.Below 2 function
handleClick = (fileUploader) => {
fileUploader.current.click();
// this.setState({ selectedFile: event.target.files[0] });
};
handleChangeFile = (event) => {
for (var i = 0; i < event.target.files.length; i++) {
const fileUploaded = event.target.files[i];
this.setState({ uploadedFileName: fileUploaded.name });
this.setState({ uploadedFileType: fileUploaded.type });
this.setState({
selectedFiles: this.state.selectedFiles.concat(fileUploaded)
});
}
console.log(this.state.selectedFiles);
};
Inside render
const decription = this.state.selectedFiles.map((item) => {item.name}
I found a way to solve this.
handleChangeFile = (event) => {
var temp = [];
for (var i = 0; i < event.target.files.length; i++) {
temp.push(event.target.files[i]);
}
this.setState({
selectedFiles: this.state.selectedFiles.concat(temp)
});
};
We must create a temp array. This is easy.
I'm experience an issue in react native where when the array i have in my state is behaving very strangely. It says i have content in the array, but the array.length === 0. Here is a screenshot of my chatrooms array to show you what i mean (this is at the beginning of my FlatList component (receiving props.chatrooms array)
console.log('props.chatrooms')
console.log(props.chatrooms)
console.log(props.chatrooms.length)
I'm grabbing all the private and group chatIds, then making a call to those chatrooms to get the details of the users. Here is how i'm pulling the information:
componentDidMount() {
this.setState({ isLoading: true })
this.props.navigation.addListener('focus', () => {
//? Refactor to pull userId from Redux Store
let friendsArray = []
let chatrooms = []
let privateChatIds = []
let groupChatIds = []
AsyncStorage.getItem('userId').then(userId => {
let currentUser = {}
firebase.firestore().collection('users').doc(userId).get().then(snapshot => {
currentUser = snapshot.data()
}).then(() => this.setState({ currentUser: currentUser }))
firebase.firestore().collection('users').doc(userId).collection('friends').get().then((snapshot) => {
if (!snapshot.empty) {
snapshot.forEach((doc) => {
friendsArray.push(doc.data())
privateChatIds.push(doc.data().chatroomId)
});
} else {
console.log('Nothing to Grab')
}
}).then(() => this.setState({ friends: friendsArray }))
// get each array and put into the chatroomsArray
firebase.firestore().collection('users').doc(userId).collection('groupChatrooms').get().then((snapshot) => {
if (!snapshot.empty) {
snapshot.forEach((doc) => {
groupChatIds.push(doc.data().key)
})
}
//! will want to limit this number to like 10-15 or something
}).then(() => {
for (let i = 0; i < privateChatIds.length; i++) {
firebase.firestore().collection('chatrooms').doc('private').collection(privateChatIds[i]).doc('info').get().then((snapshot) => {
chatrooms.push(snapshot.data())
})
}
for (let i = 0; i < groupChatIds.length; i++) {
firebase.firestore().collection('chatrooms').doc('group').collection(groupChatIds[i]).doc('info').get().then((snapshot) => {
chatrooms.push(snapshot.data())
})
}
}).then(() => {
console.log('chatrooms')
console.log(chatrooms)
this.setState({ chatrooms, isLoading: false })
})
})
})
}
is my code perfect? no, probably pretty terrible performance-wise, but i'm just trying to get it to work. I figure i'm resetting the chatrooms array or something, but why would it log as an array of items i want but then immediately after log as .length === 0??? Help!
Update: I'm seeing this content render from the flatlist initially and then it disappears
I cant understand why my renderMovies() function dont wanna update my component state.data and i cant render component on my screen ?!
Everithing goes ok until renderMovies function.. I think this.setState(newState) in my fetchPostData function is working incorrect... Do somebody know how to fix it? I tried different ways but i cant solve this issue.
class Movies extends React.Component {
constructor(props) {
super(props)
this.state = { data: {}}
this.fetchPostData = this.fetchPostData.bind(this)
this.renderMovies = this.renderMovies.bind(this)
this.populatePageAfterFetch = this.populatePageAfterFetch.bind(this)
}
componentDidMount() {
this.fetchPostData()
}
fetchPostData() {
fetch(`http://localhost/reacttest/wp-json/wp/v2/movies?per_page=100`)
.then(response => response.json())
.then(myJSON => {
let objLength = Object.keys(myJSON).length
let newState = this.state;
for (let i = 0; i < objLength; i++) {
let objKey = Object.values(myJSON)[i].title.rendered;
// console.log(objKey)
let currentMovie = newState.data[objKey];
currentMovie = {};
currentMovie.name = Object.values(myJSON)[i].title.rendered;
currentMovie.description = Object.values(myJSON)[i].content.rendered;
currentMovie.featured_image = Object.values(myJSON)[i]['featured_image_url'];
currentMovie.genre = Object.values(myJSON)[i]['genre'];
}
this.setState(newState)
})
}
renderMovies() {
if(this.state.data) {
const moviesArray = Object.values(this.state.data)
console.log(moviesArray)
return Object.values(moviesArray).map((movie, index) => this.populatePageAfterFetch(movie, index))
}
}
populatePageAfterFetch(movie, index) {
if (this.state.data) {
return (
<div key={index} index={index}>
<h2>{movie.title}</h2>
<h3>{movie.genre}</h3>
<p>{movie.description}</p>
</div>
)
}
}
render() {
return (
<div>
<h1>Movies</h1>
<div>{this.renderMovies()}</div>
</div>
)
}
}
When i try to console.log(moviesArray) it show me:
Issue
You save current state into a variable named newState, never update it, and then save the same object reference back into state. React state never really updates.
let newState = this.state;
for (let i = 0; i < objLength; i++) {
...
}
this.setState(newState);
Additionally you mutate state
let currentMovie = newState.data[objKey];
currentMovie = {};
But this doesn't work either since initial state is an empty object so newState.data[objKey] is aways undefined. (so nothing is ever actually mutated)
Solution
It appears as though you intended to map the myJSON data/values into movie objects to update this.state.data. May I suggest this solution. The key is to always create new object references for any object you update.
fetchPostData() {
fetch(`http://localhost/reacttest/wp-json/wp/v2/movies?per_page=100`)
.then(response => response.json())
.then(myJSON => {
this.setState(prevState => ({
// array::reduce over the JSON values
data: Object.values(myJSON).reduce((movies, movie) => {
// compute movie key
const name = movie.title.rendered;
return {
...movies,
[name]: {
...movies[name], // copy any existing movie properties
// merge in new/updated properties
name,
description: movie.content.rendered,
featured_image: movie.featured_image_url,
genre: movie.genre,
},
}
}, { ...prevState.data }) // use previous state as initial value for reduce
}))
})
}
I have a series of data in which there is a form in every item. I try to use index in onSubmit event and when I check index of for loop in console, it shows the correct index, but when I check index of
handleSubmitR=(e, DetailsRoom, index)=>{console.log(index)}
it is different from the index in for loop.
For example, if I have 3 forms in one item the result of the index in for loop is
'01','02' ,'03'
but in onsubmit event the result of index is **
'03','03','03'
Any suggestions?
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
resultEdit: {},
};
$.ajax({
url:"/json.bc",
type:"post",
success: (result) => {
this.setState({data: eval(result)});
}
})
}
renderHotel(){
return this.state.data.sort((a, b) => a.total - b.total).map((item,i)=>{
return (
<div class="items">
{this.renderDetailsRoom(item,i)}
</div>
)
})
}
renderDetailsRoom(DetailsRoom,i){
let lenfamilies = DetailsRoom.families.length
var indents =[];
for(var j = 0 ;j <lenfamilies;j++){
var numF = i;
var numS = j;
var stingF = numF.toString();
var stingS = numS.toString();
var index= stingF+stingS
**////
<!-----e.g. For two forms the result of consol.log(index) = '00' and '01'----->
/////**
indents.push(<form method="post" key={index} action={this.renderAction(DetailsRoom)} onSubmit={e => this.handleSubmitR(e, DetailsRoom, index)}><div class="Result">{this.state.resultEdit[index]}</div></form>)
}
return(
indents
)
}
handleSubmitR=(e, DetailsRoom, index)=>{
////
<!-----but the result of consol.log(index) in this part for both form are '01'----->
/////
console.log(index)
e.preventDefault();
return this.setState( prevState => ({
resultEdit: { ...prevState.resultEdit, [index]:'submitted'},
})) }
render() {
return (
<div>{this.renderHotel()}</div>);
}
}
ReactDOM.render(<App/>, document.getElementById('Result'));
i'm trying to use setState to update one property of a sub object of the state. What is the correct way to do this? I want to access the state and define which part I want to update, as opposed to update the entire state with a new state. Hope that makes sense...
class BooksApp extends React.Component {
state = {
books: []
}
componentDidMount() {
BooksAPI.getAll().then((books) => {
this.setState({books})
})
}
selectStateUpdate = (book,shelf) => {
this.updateShelf(book, shelf);
}
updateShelf = (book, shelf) => {
BooksAPI.update(book, shelf)
.then(() => {
for (var i=0; this.state.length < i; i++) {
if (this.state.title === book.title) {
this.setState({
books[i].shelf: book.shelf
})
}
}
})
}
Try to change your state changing part to:
this.setState({
books: this.state.books.map((item, index) =>
index === i ? {...item, shelf: book.shelf} : item
)
})