Why my componentWillRecieveProps not call when props changes Reactjs? - javascript

Here, my componentWillReceiveProps not call. Actually what I am doing.I have 2 component but I want to show my component conditionally.
Let's talk step by step ::=>
1. Here i am using switch to call my component.
case 4 :
return(
<Hotspotmergepreview
xml = {this.state.xml}
remedStatus = {this.state.remediationToggle}
showAns = {this.showAns}
/>
);
2. Above i call hotspotmergepreview component and i pass some data(xml) using props.
this is my component where i call my both component based on conditionally.
import React from 'react';
import HotspotPreview from '../components/HotspotPreview';
import Hotspotnewpreview from '../components/Hotspotnewpreview';
export default class Hotspotmergepreview extends React.Component {
constructor(props) {
super(props)
self = this
this.cType = ''
this.state = {
xml:''
}
}
componentWillReceiveProps(nextProps) {
if(this.props.xml != nextProps.xml) {
const newXml = XMLToJSON(nextProps.xml)
this.cType = newXml.smxml.div._type
this.setState({
xml:nextProps.xml
})
}
}
render(){
if(this.cType == 'w' || this.cType == 's' || this.cType == 'p') {
console.log("inside"+this.cType)
return(
<Hotspotnewpreview
xml = {this.state.xml}
remedStatus = {this.props.remediationToggle}
showAns = {this.props.showAns}
/>
);
} else {
return (
<HotspotPreview
xml = {this.state.xml}
remedStatus = {this.props.remediationToggle}
showAns = {this.props.showAns}
/>
);
}
}
}
3. my main component where i recieve all data using componentwillreceiveprops. but this lifecycle not works properly.
export default class Hotspotnewpreview extends React.Component {
constructor(props){
super(props);
self = this
this.state ={
templateType: 'default',
}
this.templateArea = this.templateArea.bind(this)
this.checkXML = this.checkXML.bind(this)
}
componentWillReceiveProps(nextProps) {
if(this.props.xml != nextProps.xml) {
const newXml = XMLToJSON(nextProps.xml)
let cData = newXml.smxml.div.__cdata
cData = cData.replace(/%{/gm,' ').replace(/}%/gm,' ')
this.receivedXML = cData.replace(/(?:\r\n|\r|\n)/g,' <br>')
this.ansString = newXml.smxml.div._correctans
if(this.ansString) {
this.correctAnswers = this.ansString.split(',')
}
this.splitType = newXml.smxml.div._type
this.checkXML(this.splitType)
this.forceUpdate();
}
}
So i don't know what i am doing wrong here.

Related

React | this.props.function inside a function will not be called

I'm working on a Checklist with React and MaterialUI consisting out of two components, one that contains the data and another one that edits it, but there occurs the problem that the called function (handleDeleteChip()), which is passed on with props, will not be executed.
Parent Component:
export default class CheckList extends React.Component {
constructor() {
super();
this.state = {
taskData: {}
}
this.handleDeleteChip = this.handleDeleteChip.bind(this)
handleDeleteChip = (chipToDelete) => () => {
let obj = this.state.taskData
delete obj[chipToDelete]
this.setState({taskData: obj})
};
render() {
return (
<div>
{
<AddToDoComponent handleDeleteChip={this.handleDeleteChip}/>
}
</div>
Child Component:
class AddToDoComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
chipData: props.taskData,
updateCondition: true
}
this.deleteHandler = this.deleteHandler.bind(this)
}
deleteHandler(chipToDelete){
this.props.handleDeleteChip(chipToDelete)
}
The definition of handleDeleteChip should be:
handleDeleteChip(chipToDelete) {
let obj = this.state.taskData
delete obj[chipToDelete]
this.setState({taskData: obj})
};
or if you are using a functional component
const handleDeleteChip = (chipToDelete) => {
....
};
Also, the brackets ({}) into the parent render are not needed.
Hope this helps you!
Try to bind this from the prop value.
export default class CheckList extends React.Component {
constructor() {
super();
this.state = {
taskData: {}
}
//Remove: this.handleDeleteChip = this.handleDeleteChip.bind(this)
handleDeleteChip = (chipToDelete) => () => {
let obj = this.state.taskData
delete obj[chipToDelete]
this.setState({taskData: obj})
};
render() {
return (
<div>
{
<AddToDoComponent handleDeleteChip={this.handleDeleteChip.bind(this)}/>
}
</div>

how to call multiple methods in onClick in react?

I have two components (Parent component & Child component) in my react app. I have two button clicks in my child component and I need to pass two props to the parent component. I use the code as follows.
The problem is, I can't include both methods in the parent component's element, but I need to. How can I use both edituser and deleteuser functions in the parent component?
Child component:
class EnhancedTable extends React.Component {
constructor(props){
super(props);
this.state = {
userID: 10
};
this.editByUserId = this.sendUserId.bind(this);
this.DeleteByUserId = this.sendUserId.bind(this);
}
editByUserId() {
this.props.onClick(this.state.userID);
}
DeleteByUserId() {
this.props.onClick(this.state.userID);
}
render() {
return (
<button onClick={this.sendUserId}>
<BorderColorIcon onClick={this.editUserById} className="action margin-r" />
<DeleteIcon onClick={this.deleteUserById} className="action margin-r" />
</button>
)
}
}
Parent component:
Import EnhancedTable from './EnhancedTable';
class Users extends Component {
constructor(props) {
super(props);
this.state = {
userID: null
};
this.editUser = this.editUser.bind(this);
this.deleteUser = this.deleteUser.bind(this);
}
editUser(idd) {
this.setState({
userID : idd
})
console.log("User Edited");
}
deleteUser(idd) {
this.setState({
userID : idd
})
console.log("User Deleted");
}
render() {
return(
<EnhancedTable onClick = {(e)=>{this.editUser; this.deleteUser;}}/>
)
}
}
You missed your ()
<EnhancedTable onClick = {(e)=>{this.editUser(); this.deleteUser();}}/>
You are doing it right in
<EnhancedTable onClick = {(e)=>{this.editUser; this.deleteUser;}}/>
A minor change is needed:
<EnhancedTable onClick = {(e)=>{this.editUser(e); this.deleteUser(e);}}/>
A quick reference for what changed here:
let x = () => {
console.log('hello');
}
x; // This simply does nothing as it is just a reference to the function
x(); // This instead invokes the function

React load value and allow user to alter value within component

I'm new to React (16.4.2), and I'm trying to understand the way it works. I don't want to complicate things with redux; I just want to know about the core react library.
I have an application, and (eventually down the children chain) there is an input, which is a component, RangeInput. It's just a wrapper component for an input.
The problem is two parts
I should be able to change the value within the range (as a user)
if there is data in the local storage, it should load it the first time. This also means that the user should still be able to alter/change the input value.
Right now with this, I see to only be able to do one of the other. I know I'm not understanding something here.
What needs to happen?
Thanks,
Kelly
Here are the classes:
export class RangeInput extends React.Component {
constructor(props) {
super(props);
this.ds = new DataStore();
this.state = {
value: props.value
};
}
static getDerivedStateFromProps(props, state) {
console.log('props', props, 'state', state);
if (props.value !== state.value) {
return {value: props.value};
}
return null;
}
onChange(event) {
const target = event.target;
this.setState({
value: target.value
});
if (this.props.onChange) {
this.props.onChange({value: target.value});
}
}
onKeyUp(event) {
if (event.keyCode !== 9) {
return;
}
const target = event.target;
if (this.props.onChange) {
this.props.onChange({value: target.value});
}
}
render() {
return <div>
<input type="number" value={this.state.value}
onChange={this.onChange.bind(this)}
onKeyUp={this.onKeyUp.bind(this)}/>
</div>;
}
}
const DATA_LOAD = 'load';
export class Application extends React.Component {
constructor() {
super();
this.state = {
value: -1,
load = DATA_LOAD
};
}
componentDidMount() {
if (this.state.load === DATA_LOAD) {
this.state.load = DATA_CLEAN;
const eco = this.ds.getObject('the-app');
if (eco) {
this.setState({value: eco});
}
}
}
render(){
return <RangeInput value={this.state.value} />;
}
}
ReactDOM.render(
<Application/>,
document.getElementById('root')
);
I think this situation can be simplified quite a bit:
import React from 'react';
export const RangeInput = props => (
<input
value={props.value}
onChange={props.setValue} />
)
export class Application extends React.Component {
constructor(props) {
super(props);
this.state = { value: -1, };
}
componentDidMount() {
var val = localStorage.getItem('myVal');
if (val) this.setState({value: val})
}
setValue(e) {
this.setState({value: e.target.value})
localStorage.setItem('myVal', e.target.value);
}
render() {
return <RangeInput
value={this.state.value}
setValue={this.setValue.bind(this)} />;
}
}
Here we have two components: <RangeInput>, a stateless component, and <Application>, the brains behind the operation.
<Application> keeps track of the state, and passes a callback function to RangeInput. Then, on keydown, <RangeInput> passes the event object to that callback function. Application then uses the event object to update the state and the localStorage. On refresh, the last saved value is fetched from localStorage and present in the input (if available).

this.transformer.anchorSize is not a function

I was trying to make some changes in Transformer Component in React Konva and faced this error whenever I was trying to change anchor size. I followed the syntax as stated in document - https://konvajs.github.io/api/Konva.Transformer.html#validateAnchors__anchor
The issue is in anchorSize. Please help me. Here's the code -
class TransformerComponent extends React.Component {
componentDidMount () {
this.checkNode ();
}
componentDidUpdate () {
this.checkNode ();
}
checkNode() {
const stage = this.transformer.getStage();
const { selectedShapeName } = this.props;
const selectedNode = stage.findOne ('.' + selectedShapeName);
this.transformer.rotateEnabled (false);
this.transformer.anchorSize (5);
if (selectedNode === this.transformer.node()) {
return;
}
if (selectedNode) {
this.transformer.attachTo (selectedNode);
}
else {
this.transformer.detach();
}
this.transformer.getLayer().batchDraw();
}
render() {
return (
<Transformer
ref = {node => {
this.transformer = node;
}}
/>
);
}
}
anchorSize is a very new property introduces recently. Try to update Konva to the latest version.
You need to bind this for checkNode() as down below:
class TransformerComponent extends React.Component {
constructor(props) {
super(props)
this.checkNode = this.checkNode.bind(this)
}
...

How to setState from child component in React

I would like to set state of parent component from child component. I tried using props however its giving error Uncaught TypeError: this.props.setTopicClicked is not a function. And is there more efficient way for setting state of parent component instead of using props? I would like to set state of isTopicClicked: true
main-controller.jsx
import {React, ReactDOM} from '../../../build/react';
import SelectedTopicPage from '../selected-topic-page.jsx';
import TopicsList from '../topic-list.jsx';
import topicPageData from '../../content/json/topic-page-data.js';
export default class MainController extends React.Component {
state = {
isTopicClicked: false,
topicPageData
};
onClick(topicID) {
this.setState({
isTopicClicked: true,
topicsID: topicID
});
};
setTopicClicked(event){
this.setState({isTopicClicked: event});
};
render() {
return (
<div className="row">
{this.state.isTopicClicked
? <SelectedTopicPage topicsID={this.state.topicsID} key={this.state.topicsID} topicPageData={topicPageData}/>
: <TopicsList onClick={ this.onClick.bind(this) }/>}
</div>
);
}
};
selected-topic-page.jsx
import {React, ReactDOM} from '../../build/react';
import SelectedTopicPageMarkup from './selected-topic-page-markup.jsx';
import NextPrevBtn from './next-prev-btn.jsx';
export default class SelectedTopicPage extends React.Component {
state = {
topicPageNo: 0,
total_selected_topic_pages: 1
};
navigateBack(topicPageNo) {
if (this.state.topicPageNo > 0){
topicPageNo = this.state.topicPageNo - 1;
}
else {
topicPageNo = 0;
}
this.setState({topicPageNo : topicPageNo});
};
navigateNext(totalPagesInSelectedTopic) {
let topicPageNo;
if (totalPagesInSelectedTopic > this.state.topicPageNo + 1){
topicPageNo = this.state.topicPageNo + 1;
}
else if (totalPagesInSelectedTopic == this.state.topicPageNo + 1) {
this.props.setTopicClicked(true);
}
else {
topicPageNo = this.state.topicPageNo;
}
this.setState({topicPageNo : topicPageNo});
};
render() {
let topicsID = this.props.topicsID;
let topicPageNo = this.state.topicPageNo;
return (
<div>
{this.props.topicPageData.filter(function(topicPage) {
// if condition is true, item is not filtered out
return topicPage.topic_no === topicsID;
}).map(function (topicPage) {
let totalPagesInSelectedTopic = topicPage.topic_pages.length;
return (
<div>
<div>
<SelectedTopicPageMarkup headline={topicPage.topic_pages[0].headline} key={topicPage.topic_no}>
{topicPage.topic_pages[topicPageNo].description}
</SelectedTopicPageMarkup>
</div>
<div>
<NextPrevBtn moveNext={this.navigateNext.bind(this, totalPagesInSelectedTopic)} key={topicPage.topic_no} moveBack={this.navigateBack.bind(this, topicPageNo)}/>
</div>
</div>
);
}.bind(this))}
</div>
);
};
};
It seems you forgot to pass setTopicClicked to the child:
setTopicClicked={this.setTopicClicked.bind(this)}
Your <SelectedTopicPage /> does not contain setTopicClicked as props which results into the error
<SelectedTopicPage
topicsID={this.state.topicsID}
key={this.state.topicsID}
topicPageData={topicPageData}/>
You can try using a flux implementation to handle the state of your application and just pass props to the component. Otherwise, I think you're stuck in passing in setting the state using the component or its children.

Categories

Resources