0

I'm trying to make my component re-render and fetch new data when the props is changed but I can't make it work.

export default class InfoTagEditor extends React.PureComponent<Props, State> {
    componentDidUpdate() {
        $.get('/webapi/getData?componentId=' + this.props.id, function (data) {
            this.setState({value: data});
            this.initComponentsDropdownlist();
        }.bind(this));
    }
}

But this doesn't update the state at all...

Does anyone know what's wrong?

Kendo Editor in Render function:

Render(){
    return   <Editor
    name={"Editor"}
    value={this.state.value}
    change={this.onChangeEditor}
    resizable={true}
    />
}

What worked for me was:

shouldComponentUpdate(nextProps)
{
    if (this.props.Id !== nextProps.Id) {
        $.get('/webapi/GetData?Id=' + nextProps.Id, function (data) {
            this.setState({value: data});
            $('#editor').data('kendoEditor').value(this.state.value)
            return true;
        }.bind(this));
    }

    if (this.props.name !== nextProps.name) {
        return true;
    }

    return false;
}

But would this be the correct way of doing this? The Id and Name is corresponding, which means that everytime there is a new ID, there will also be a new Name.

Should I do this separate

this.setState({ value: data });
$('#editor').data('kendoEditor').value(this.state.value)

or

 this.setState({ value: data },  
 $('#editor').data('kendoEditor').value(this.state.value)); 

Managed to get this work:

componentDidUpdate(prevProps) {
    if(this.props.id!== prevProps.id) {
        $.get('/webapi/GetData?id=' + this.props.id, function (data) {
            this.setState({ editorValue: data }, $('#editor').data('kendoEditor').value(data)); 
        }.bind(this));
     }
}

Is this a correct way of doing the callback? and does it looks fine? :) or should I move the $('#editor').data('kendoEditor').value(data) outside the setState?

  • Possible duplicate of [What is the difference between state and props in React?](https://stackoverflow.com/questions/27991366/what-is-the-difference-between-state-and-props-in-react) – mooga May 08 '19 at 11:48
  • I think you should store your props in state and then instead of using props directly use state – Faiz Khan May 08 '19 at 11:50
  • is the request fired? do you get a response? do you get any exception? – Nsevens May 08 '19 at 11:55
  • 1
    call `this.initComponentsDropdownlist()` in `setState` callback, otherwise it can work on old data – xadm May 08 '19 at 12:10
  • Could you provide an example? –  May 08 '19 at 12:15

2 Answers2

0

First you should add a condition in order to prevent infinite loop (setState -> componentDidUpdate -> setState -> componentDidUpdate ....) : https://reactjs.org/docs/react-component.html#componentdidupdate

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop

Here is a possible solution

componentDidUpdate(prevProps) {
    if(this.props.id !== prevProps.id) {
        $.get('/webapi/getData?componentId=' + this.props.id, (data) => {
           this.setState({ value: data });
           this.initComponentsDropdownlist();
        });
     }
}

Note that if the method initComponentsDropdownlist uses this.state.value, it should be called when setState is completed, so you should replace :

this.setState({ value: data });
this.initComponentsDropdownlist();

by

 this.setState({ value: data }, this.initComponentsDropdownlist);
Olivier Boissé
  • 15,834
  • 6
  • 38
  • 56
  • I tried this, it seem like it should work? But the state with the data isn't updated it seems in my editor. Since it use the value state. –  May 08 '19 at 12:19
  • can you show us the code in the method `initComponentsDropdownlist` ? Does it use variable `this.state.value` ? – Olivier Boissé May 08 '19 at 12:21
  • I updated the post with the component that uses this. Sorry but the initComponentsDropdownlist is wrong, it should be the editor that uses the value. –  May 08 '19 at 12:38
  • It seems like this package with the editor: https://www.npmjs.com/package/@progress/kendo-editor-react-wrapper has problem with updating... I tried to remove the editor and the state changed perfectly. How can I fix this? –  May 08 '19 at 13:27
  • I don't really know the `kendo` library, do you have a link to the documentation of this component ? – Olivier Boissé May 08 '19 at 13:36
  • Hello @Olivier Boissé, should it be this.setState({ value: data }, this.initComponentsDropdownlist); or this.setState({ value: data }, this.initComponentsDropdownlist()); –  May 08 '19 at 13:58
  • the second argument is a callback so it should be `this.setState({ value: data }, this.initComponentsDropdownlist);` or `this.setState({ value: data }, () => this.initComponentsDropdownlist());` – Olivier Boissé May 08 '19 at 14:02
  • What does a callback mean my friend? :) @Olivier Boissé Here is the documentation for the library: https://docs.telerik.com/kendo-ui/controls/editors/editor/overview –  May 08 '19 at 14:21
  • I tried to do this after the $('#editor').data('kendoEditor').value(this.state.editorValue); But I'm getting GetSelection error. I also tried to call InitEditor, but it seem to just created another editor each time the componentdidupdate, instead of just updating the value. –  May 08 '19 at 14:25
  • Are you using Kendo React controls (if not, perhaps you should?)? According to https://www.telerik.com/kendo-react-ui/components/editor/api/EditorProps/ there is no `value` or `change` prop. Are you sure you're working with the correct version etc? Have you checked the sample? https://www.telerik.com/kendo-react-ui/components/editor/content/ – Nsevens May 08 '19 at 14:27
  • I'm using this one @NSevens docs.telerik.com/kendo-ui/controls/editors/editor/overview –  May 08 '19 at 14:46
  • you're running a react application, why not use React components from the same library? they are much more integrated in the react lifecycle – Nsevens May 08 '19 at 15:04
  • When I put it outside the Jquery Get, it seem to work fine. But the editor value only appear on the next re-render when I update the prop.... –  May 08 '19 at 15:21
  • a callback is simply ia function that is passed as an argument of another function. it's often used when you want want to execute code asynchronously (after the end of an operation like an ajax call) – Olivier Boissé May 08 '19 at 16:42
  • @OlivierBoissé I have updated the post. Could you check and tell me if there is any way I could do this different? Or if this is a bad way of doing it? –  May 08 '19 at 17:26
  • you don't need `return true` or `return false` in `componentDidUpdate`, so remove them. `setState` is **asynchronous** so `$('#editor').data('kendoEditor').value(this.state.value)` is wrong, you should replace it by `$('#editor').data('kendoEditor').value(data)` – Olivier Boissé May 08 '19 at 17:31
  • As you are using `jQuery` to update the value of your editor, the state `value` seems to become useless, maybe you don't need a state anymore – Olivier Boissé May 08 '19 at 17:33
  • Should I include componentDidUpdate? Since I'm not sure what to put in there. But in your opinion, should it work in componentDidUpdate? Because it seems like when the jquery set value, I need to re-render my component in order to "see the new" changes. –  May 08 '19 at 17:50
  • `this.setState({ editorValue: data }); $('#editor').data('kendoEditor').value(data));` – Olivier Boissé May 08 '19 at 18:55
-1

use componentWillReceiveProps

export default class InfoTagEditor extends React.PureComponent {        
   componentWillReceiveProps(props)
   {
           $.get('/webapi/getData?componentId=' + props.id, function (data) 
           {
                this.setState({ value: data });
                this.initComponentsDropdownlist();
            }.bind(this));
    }
}
sarvon ks
  • 626
  • 3
  • 10