I have a working Table component in a Nextjs app that only renders the first time but if I change the data it doesn't update.
render() {
const data = this.props.data
console.log(data) // this shows the new data changing in the console but the table doesn't update
return (
<Table dataSource={data} columns={this.state.columns} />
)
}
The same version it works OK using Create React App
Thanks in advance
Update:
Now works if I change the data to force array modification with:
const data = this.props.data.slice(0,this.props.data.length)
Is there any cleaner solution?
Related
My application contains a view that is a functional react component. I'm trying to add a timestamp at the bottom of the view displaying the date and time when the user navigated to this view. I'm wondering what would be appropriate way to implement this using hooks. I guess one option would be to use const [date] = useState(new Date()) and simply provide no setter for the state since it would never change. However, this makes me wonder if useState is the appropriate hook to begin with. Should I just do const date = new Date() in the component body or would that have some unexpected side effects?
For what you intend to accomplish, the code below would work just fine:
// solution # 1
function MyComponent() {
const [time, setTime] = useState(new Date());
return (
<div>
View created at {time.toLocaleTimeString()}
</div>
)
}
However, it is important to know that it is not following React rules. That is because we are calling new Date() from inside the component, making it impure. React expects the components to be pure functions. This means that it should return the same thing for the same input. But React cannot guarantee that a function component doesn't have side effects, and that is why that first solution would work just fine.
According to this gist, a better approach for this task would be:
// solution # 2
function MyComponent() {
const [time, setTime] = useState<Date>();
useEffect(() => {
setTime(new Date());
}}, [])
return (
<div>
View created at {time && time.toLocaleTimeString()}
</div>
)
}
Roughly speaking, all side effects should live inside useEffect. So, things like calling an external API or calling impure functions (such as Math.random() or Date.now()) should be there. From my understanding, this solution would be more appropriate.
If we are not obeying React guidelines, the library might not work as advertised. Before version 18, React had only synchronous rendering. This means that the moment the render phase is kicked off (either by a initial render or by a state update), nothing could interrupt it from committing those updates to the browser. In that situation, I don't think the first solution I presented would be problematic. But, in React 18, we have the concurrent mode features by which rendering can be interrupted before the diffs are committed to the screen. With that, React can be more intelligent about how it breaks up all the work it needs to do (for example, we can now define high-priority updates).
In order for these new APIs to work properly, React assumes that the components are pure functions, which means that it has no side effects. These APIs are very new and there are still many more additional features coming in. I am not quite sure about how sensitive they are to function impurity, but I believe our second solution (with all side effects living inside the useEffect) is a better bet for this task.
The following seems to work. Still not sure if this is optimal though.
import React from 'react'
export function View(_props) {
const [viewCreated] = React.useState(Date.now())
return (
<div>
View created {String(new Date(viewCreated))}
</div>
)
}
useState(new Date()) is better. Here is complete component
import React, { useState , useEffect } from 'react'
export const DateTime = () => {
var [date,setDate] = useState(new Date());
useEffect(() => {
var timer = setInterval(()=>setDate(new Date()), 1000 )
return function cleanup() {
clearInterval(timer)
}
});
return(
<div>
<p> Time : {date.toLocaleTimeString()}</p>
<p> Date : {date.toLocaleDateString()}</p>
</div>
)
}
export default DateTime
I'm having issue getting the React Fabric UI DetailsList to work with React Hooks. It renders, but the selection part does not. Whenever, you select a row, I expect the count of the selection to be updated. However, i'm not seeing that. It looks like the selection component items never get updated even thou the UI shows it being selected. I'm also seeing the onSelectionChange being triggered when you select a row. Now sure if its because i'm using react hooks or what
I took the provided class example which works:
[Codepen]https://codepen.io/pen/?&editable=true (Example)
Same as the original but stripped down
[Codepen]https://codepen.io/darewreckk/pen/NQRWEd?editors=1111
converted it to a react hook component. I would expect the same thing, but i'm not and can't figure out what's different.
Modified Example with Hooks
[Codepen]https://codepen.io/darewreckk/pen/GVjRNb?editors=1111
Any advice appreciated,
Thanks,
Derek
The selection count is stored on the Selection object that you are creating. You could log it out like so:
const _selection = new Selection({
onSelectionChanged: () => {
console.log('Selected count:' + _selection.count);
}
});
You can set the value of selectionCount and selectionDetails whenever onSelectionChanged is called:
const _selection = new Selection({
onSelectionChanged: () => {
setSelectionCount(_selection.count);
setSelectionDetails(`${_selection.count} items selected`)
}
});
As a side note: If you want selectionDetails to update when selectionCount updates, you can use the useEffect hook:
React.useEffect(() => {
setSelectionDetails(`${selectionCount} items selected`);
}, [selectionCount]);
The above effect will run whenever selectionCount updates, and so in turn update selectionDetails.
I am using Laravel+VueJs. I stuck on one thing. I am trying to load a new view using laravel route. I am using axios.
getRelatedChat(id) {
return axios.get('/chat/'+id).then(({ data }) => {
// document.write(data)
});
}
The code of whole view is coming in console as output, but i want to load it like window.url does for us. Have no idea how to do.
Vue has its own router. If you want to load a new page you can still use axios to get the data you want to show in the next page you want to open. Just try the Vue Router
I was making a nonsense. Actually there is no need to load the view. I can update some variable that are using on present component just like this:
axios.get('/chat/json/'+id).then(({ data }) => {
this.messages =data.messages;
this.withUser = data.user;
}
I'm developing an app that receives data from API and should store it in some kind of cache to bind it to UI views. This data is also shared among several views and any change to it should be reflected in views. What is the best and fastest option for NativeScript so far? Would be awesome to have something similar to SenchaTouch stores / models with proxy. Thanks.
Just create a singleton and request/import that, just as you would in any other Javascript app. As long as you keep your data in an Observable and any changes to it will instantly be reflected in the views.
E.g.
file: myData.js
var observableArray = require("data/observable-array");
var observable = require("data/observable");
var DATA = new observable.Observable({
something: 'a value here',
somethingElse: 1
somethingMany: new observableArray.ObservableArray(['a', 'b', 'c'])
});
exports.getData = function() { return DATA; };
exports.fetchFromAPI = function() { /* something that fetches and updates DATA */ }
In any file where you want to read that data:
var data = require("./myData.js");
console.log(data.getData());
Read more about Observables in NativeScript
I just started using rivets js a couple of days before. So i am studying it. But got stuck myself
I have created a fiddle here
What i want to do is. I want to remove the data from the div and put another set of data's inside that
So at first the binding is working. But second time when i empty the div and once again bind Its not working
Created Fiddle
http://fiddle.jshell.net/m8j4ycj1/
function render() {
rivets.bind($("#hello"), datas);
return this;
}
rivets.bind($("#hello"), data);
setTimeout(function(){
debugger;
$("#hello").empty();
render();
},1000)
In this code the first binding is working but not after the setTimeout
as i understand you just want to empty the div?
so try to emtpy the model.
if data is:
data = { username: '12345' };
do
data.username = '';
and the view should be updated automatically
greez