In one render function I create 1-3 components BigText
return (<div>{ d.sql[0] !== null ? <BigText content={d.sql[0]}>SQL</BigText> : <span> </span> }
{ d.event[0] !== null ? <BigText content={d.event[0]}>Event</BigText> : <span> </span>}
{ d.stacktrace[0] !== null ? <BigText content={d.stacktrace[0]}>Trace</BigText> : <span> </span>}</div>)
d is a real object Object {sql: Array[1], stacktrace: Array[1], event: Array[1]}. This code seems correct.
But the object passed as content is not present in the BigText component render.
class BigText extends React.Component {
constructor(props) {
super(props);
this.toggleViewer = this.toggleViewer.bind(this);
console.log(this);
}
toggleViewer() {
console.log(this);
this.props.viewerToggle(this.props.content);
}
render() {
console.log(this);
return (<FlatButton primary={true} onTouchTap={this.toggleViewer}>{this.props.children}</FlatButton>)
}
}
BigText.propTypes = {
class: React.PropTypes.string,
content: React.PropTypes.any.isRequered
}
Logged this object. As you see below props.content is null when component has been called to render, it is also null when constructor has been called:
BigText
props
children: "SQL"
content: null
isViewerOpened: false
viewerToggle: function ()
__proto__: Object
context: Object
refs: Object
updater: Object
...
Where to dig to solve this issue?
Related
Is it possible to access a state value in constructor, and use it in a different state value in same constructor? See example below.
class App extends Component {
constructor(props){
super(props);
this.state = {
values1: {
value1: "value 1"
},
values2: {
value2: "value 2"
},
selected: {
selectedValue: `Selected value is: ${this.state.values1.value1}`
}
}
}
}
It will not work.
But you can set another variable's value in componentDidMount.
See my example :
class App extends Component {
constructor(props){
super(props);
this.state = {
values1: {
value1: "value 1"
},
values2: {
value2: "value 2"
},
}
}
componentDidMount(){
this.setState({selectedValue: "Selected value is: "+ this.state.values1.value1});
}
render() {
return (
<div>
<p>
{this.state.selectedValue}
</p>
</div>
)
}
}
Here is a working example - https://stackblitz.com/edit/react-2ra5ht
Yes it is but you would have to use the setState() method to do so
You would declare the selected state above then within the constructor you could then usethis.setState({selected: this.state.values1.value1}) to set the state.
Yes, you approach will work with small modification. state is plain JavaScript object, so you may assign new properties to it several times in constructor.
constructor () {
super ();
this.state = {
values1: {
value1: "value 1"
},
values2: {
value2: "value 2"
}
}
this.state.selected = {
selectedValue: "Selected value is: " + this.state.values1.value1
}
}
And sample
I was trying to put an image as an object into state and pass the state as a props in react but it's not passing anything.
import xaprikaScreen from "./images/xaprikaScreenShot.jpg";
import linguadenScreen from "./images/linguadenScreenShot.jpg";
export class Portfolio extends Component {
constructor() {
super();
this.state = {
currentProject: 0,
projects: [
{
id: 1,
projectName: "Linguaden.com",
projectLink: "www.linguaden.com",
githubLink: "",
displayPicture: { linguadenScreen },
projectDescription: ""
},
{
id: 2,
projectName: "Xaprika.com",
projectLink: "www.Xaprika.com",
githubLink: "",
displayPicture: { xaprikaScreen },
projectDescription: ""
}
]
};
}
render() {
return (
<Projects imageSource={this.state.projects[this.state.currentProject["displayPicture"]}/>
);
}
}
}
Here i have imported 2 images as an object, then i have assigned them into state and then i am trying to pass those variables as props.
The problem here is that you're doing this.state.currentProject["displayPicture"]. The value of currentProject is 0, and 0.displayPicture is undefined. You're then doing this.state.projects[this.state.currentProject["displayPicture"], which not only doesn't have a closing bracket, even if it did that would be equivalent to this.state.projects[undefined] which is also undefined.
Replace your render function with the below code and it should work.
render() {
return (
<Projects imageSource={this.state.projects[this.state.currentProject].displayPicture} />
);
}
I am getting
Uncaught TypeError: Cannot read property 'openModal' of undefined
at onClick
with the following react component:
class ReactReduxTabs extends React.Component {
constructor(props){
super(props);
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.render_response_json_modal = this.render_response_json_modal.bind(this);
this.state = {tabIndex: 1, isModelOpen: false, modalText: "blah blah blah"};
}
openModal() {
console.log("open modal");
this.setState({ isModalOpen: true })
}
closeModal() {
this.setState({ isModalOpen: false })
}
render_response_json_modal(headers, target_header) {
return add_rendering(
headers,
target_header,
function(val, row) {
return (<p onClick={() => {this.openModal()} }>yaaaaaaa</p>)
}
)
}
render() {
if (orderMetricsFetched == true) {
order_metrics.error_report_failed_orders.headers = this.render_response_json_modal(order_metrics.error_report_failed_orders.headers, 'RESPONSE', this.openModal)
return (
<div className="card">
<ReduxDataTable data={order_metrics.error_report_failed_orders}/>
</div>
What add_rendering does is take something like
headers = ['Header 1', 'Header 2']
and if you target Header 1 change to
headers= [
{title: 'Header 1', render: function() { ...returns what should go in the table cell...} },
'Header 2'
]
The issue seems to be with the this context as the table cell is clicked. When the table cell is clicked, it should call the component's openModal method.
The good new is it's very close, the table renders as it should, with each RESPONSE column cell having the random 'yaaaaa' inside, proving the add_rendering of render_response_json_modal worked. There are no errors until I click on each RESPONSE cell (one of the 'yaaaa'), where I see this print in console:
here:
return (<p onClick={() => {this.openModal()} }>yaaaaaaa</p>)
this refers to the function scope not the outer scope (that is what you want), a quick fix is to save a reference of this outside the function and use that.
var self = this;
return add_rendering(
headers,
target_header,
function(val, row) {
return (<p onClick={() => {self.openModal()} }>yaaaaaaa</p>)
})
);
By the way, the exception says that this is undefined inside the function probably because you're using "use strict" mode.
I know I'm conceptually wrong somewhere here, but how would you arrange this type of situation? I think my confusion would be clear from the code below:
class Base {
constructor() {
this._defineProperties( this.properties );
}
_defineProperties(properties) {
properties.forEach((value, key) => {
Object.defineProperties(this, key, {
value: value,
enumerable: true
})
});
}
}
class Child extends Base {
properties: {
'title': '',
'text': ''
}
}
const obj = new Child();
child.title
child.text
I want to update/re-render the component after a new update comes up. All I am doing is:
I have a list of dealers for a casino game, what I want is to add a new dealer, and once the new dealer is added then display it in the view. It is actually happening, but in order for me to see the new dealer, I have to reload the page.
I am not updating the state, I am working with this.props. Look at my code
#connectToStores
export default class Dealers extends Component {
constructor (props) {
super(props);
this.state = {}
}
componentWillMount () {
GetDealersActions.getDealers();
}
static getStores () {
return [ GetDealersStore, CreateDealersStore ];
}
static getPropsFromStores () {
return {
...GetDealersStore.getState(),
...CreateDealersStore.getState(),
}
}
render () {
return (
<div>
{!!this.props.dealerData ?
this.props.dealerData.dealersData.map((dealer) => {
return (here I am rendering what I need);
: <p>Loading . . .</p>
</div>
}
_addDealer = () => {
CreateDealersActions.createDealer({
DealerName : this.refs.DealerName.getValue(),
CardId : this.refs.CardId.getValue(),
NickName : this.refs.NickName.getValue(),
});
}
}
as you see the component above in the code is doing the initial rendering properly, the problem comes up when you hit _addDealer(), which is not updating the component, you should reload the page in order to see the new item in the view.
If you do a console.log(this.props); within _addDealer(), you will get something like this
{params: Object, query: Object, dealerData: Object, newDealerData: null}
where dealerData holds the full data of the dealers in the view but you can't see there the new dealer created. And newDealerData remains null
so, what do you think I should do in order to update the component everytime a new prop/dealer comes up ? or how do I update the props? which is the proper method in this situation ?
here is the full code for stores and actions just in case
action
#createActions(flux)
class CreateDealersActions {
constructor () {
this.generateActions('createDealerSuccess', 'createDealerFail');
}
createDealer (data) {
const that = this;
that.dispatch();
axios.post(`${API_ENDPOINT}/create-dealer/create-dealer`, data)
.then(function success (data) {
that.actions.createDealerSuccess({data});
})
}
};
store
#createStore(flux)
class CreateDealersStore {
constructor () {
this.state = {
newDealerData : null,
};
}
#bind(CreateDealersActions.createDealerSuccess)
createDealerSuccess (data) {
this.setState({
newDealerData : data.response.config.data,
});
}
}
the Dealers component is within a tab named management, which is this one:
const menuItems = [
{ route : 'dealers', text : 'Dealers' },
{ route : 'game-info', text : 'Game Info' },
{ route : 'player-info', text : 'Players Info' },
{ route : 'money', text : 'Money' }
];
export default class Management extends React.Component {
static propTypes = {
getActivePage : React.PropTypes.func,
menuItems : React.PropTypes.arrayOf(React.PropTypes.object),
}
static contextTypes = {
router : React.PropTypes.func,
}
render () {
return (
<div>
<TabsMainMenu menuItems={menuItems} getActivePage={this._getActivePage} />
<RouteHandler />
</div>
);
}
_getActivePage = () => {
for (const i in menuItems) {
if (this.context.router.isActive(menuItems[i].route)) return parseInt(i, 10);
}
}
}