How to make this available inside render function - reactjs

This is my React component:
constructor(props) {
super(props);
this.state = {
};
this.showChart = this.showChart.bind(this)
}
showChart() {
console.log('test')
}
render() {
{this.showChart} //throws error that, this is undefined
return () (
{this.showChart} //prints test
)
}
Now, if I want to call the function from render() but outside return() what should I do?

Your Component syntax is incorrect at a few places. this is available inside render.
constructor(props) {
super(props);
this.state = {
};
this.showChart = this.showChart.bind(this)
}
showChart() {
console.log('test')
}
render() {
this.showChart()
return (
<div>{this.showChart()}</div>
)
}
EDIT:
You can also work with arrow functions to bind said functions to your component. By doing this, you don't have to bind every function. It looks a lot cleaner:
constructor(props) {
super(props);
this.state = {
};
}
showChart = () => {
console.log('test')
}
render() {
this.showChart()
return (
<div>{this.showChart()}</div>
)
}

replace {this.showChart} with this.showChart()inside the render function. So your new code should be
render(){
this.showChart();
return(
{this.showChart}
);
}

Related

console.log(this.props) undefined

In my code, I console.log(this.props) inside componentDidMount while I got undefined. I console.log(this.props) inside render() I got four outputs, for the first two all the properties are undefined, the last two are correct.
componentDidMount = () => {
const { ratingsAverage } = this.props;
console.log(ratingsAverage);
//this.setState({value: this.props.ratingsAverage})
}
render() {
console.log(this.props);
}
the output of console.log(ratingsAverage) inside componentDidMount() is undefined.
the output of console.log(this.props) inside render() is on the pic below
Try this . your component constructor should be like this
constructor(props){
super(props);
this.state = {
//states
};
}

How to receive props only after state of parent has updated?

I'm trying to build a little weather widget, where the geolocation of the user is captured in one component and then passed onto a child component which fetches the weather data (based on the location) and then eventually renders an icon indicating the current weather conditions.
I'm passing the longitude and latitude state as props to my WeatherWidget. Unfortunately, the WeatherWidget also receives the initial state null. How I can I avoid that?
Thank you for your help!
class GetGeolocation extends Component{
constructor(){
super();
this.state = {
lngt: null,
latd: null
}
}
componentDidMount(){
this.getLocation()
}
getLocation = () => {
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(position => {
this.setState({lngt: position.coords.longitude.toFixed(4)});
this.setState({latd:position.coords.latitude.toFixed(4)});
}
);
};
}
render(){
return (
<>
<WeatherWidget lngt = {this.state.lngt} latd = {this.state.latd} />
</>
)
}
class WeatherWidget extends Component{
constructor(props){
super(props);
this.state = {
weather:[]
}
}
componentWillReceiveProps(nextProps){
this.getWeather(nextProps)
}
getWeather = (location) => {
console.log(location)
// The console logs twice:
// First:
//{lngt: "-12.3456", latd: null}
//Then, the correct values:
//{lngt: "-12.3456", latd: "78,9999"}
}
Don't use componentWillReceiveProps, that will be deprecated in later versions of React.
But also, you can just setup conditional logic in your life-cycle methods to determine what code to execute.
componentWillReceiveProps(nextProps){
//condition says if both value are truthy then run code.
if(nextProps.lngt && nextProps.latd){
this.getWeather(nextProps)
}
}
You can also use componentDidUpdate()
componentDidUpdate(){
//condition says if both value are truthy then run code.
if(this.props.lngt && this.props.latd){
this.getWeather(this.props)
}
}
One option is to conditionally render in the parent component:
class GetGeolocation extends React.Component {
constructor(props) {
super(props);
this.state = {
lngt: null,
latd: null
};
}
componentDidMount() {
this.getLocation();
}
getLocation = () => {
// Simulate the network request
setTimeout(() => this.setState({ lngt: 100 }), 1000);
setTimeout(() => this.setState({ latd: 100 }), 1000);
};
render() {
const { lngt, latd } = this.state;
if (!lngt || !latd) return null;
return <WeatherWidget lngt={lngt} latd={latd} />;
}
}
class WeatherWidget extends React.Component {
constructor(props) {
super(props);
this.state = {
weather: []
};
}
componentDidMount() {
this.getWeather(this.props);
}
getWeather = location => {
console.log(location);
};
render() {
return null;
}
}

React: fire render after promise completed

Please note, that I a fetching data from AWS DynamoDB.
...
class Test extends Component {
constructor(props) {
super(props);
this.state = {
contactList: []
}
}
componentDidMount() {
var getItemsPromise = db.scan({ TableName: "tester" }).promise();
getItemsPromise.then((data) => this.setState({ contactList: data.Items }));
}
render() {
return (
<div>{this.state.contactList[0].link.S}</div>
);
}
}
export default Test;
I am trying to render the returned value, but can't. If I set
render() {
console.log(this.state.contactList[0].link.S);
return (
<div>test</div>
);
}
it works. Why is that? Why is it not working when I set it straight inline?
this.state.contactList[0] is undefined before the promise is resolved, so this.state.contactList[0].link will give rise to an error.
You could e.g. return null from the render method until the array has been filled with your objects:
class Test extends Component {
// ...
render() {
if (this.state.contactList.length === 0) {
return null;
}
return <div>{this.state.contactList[0].link.S}</div>;
}
}

Call child component function from parent

How do I call a child component function from the parent component? I've tried using refs but I can't get it to work. I get errors like, Cannot read property 'handleFilterByClass' of undefined.
Path: Parent Component
export default class StudentPage extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
newStudentUserCreated() {
console.log('newStudentUserCreated1');
this.refs.studentTable.handleTableUpdate();
}
render() {
return (
<div>
<StudentTable
studentUserProfiles={this.props.studentUserProfiles}
ref={this.studentTable}
/>
</div>
);
}
}
Path: StudentTable
export default class StudentTable extends React.Component {
constructor(props) {
super(props);
this.state = {
studentUserProfiles: props.studentUserProfiles,
};
this.handleTableUpdate = this.handleTableUpdate.bind(this);
}
handleTableUpdate = () => (event) => {
// Do stuff
}
render() {
return (
<div>
// stuff
</div>
);
}
}
UPDATE
Path StudentContainer
export default StudentContainer = withTracker(() => {
const addStudentContainerHandle = Meteor.subscribe('companyAdmin.addStudentContainer.userProfiles');
const loadingaddStudentContainerHandle = !addStudentContainerHandle.ready();
const studentUserProfiles = UserProfiles.find({ student: { $exists: true } }, { sort: { lastName: 1, firstName: 1 } }).fetch();
const studentUserProfilesExist = !loadingaddStudentContainerHandle && !!studentUserProfiles;
return {
studentUserProfiles: studentUserProfilesExist ? studentUserProfiles : [],
};
})(StudentPage);
My design here is: component (Child 1) creates a new studentProfile. Parent component is notified ... which then tells component (Child 2) to run a function to update the state of the table data.
I'm paraphrasing the OP's comment here but it seems the basic idea is for a child component to update a sibling child.
One solution is to use refs.
In this solution we have the Parent pass a function to ChildOne via props. When ChildOne calls this function the Parent then via a ref calls ChildTwo's updateTable function.
Docs: https://reactjs.org/docs/refs-and-the-dom.html
Demo (open console to view result): https://codesandbox.io/s/9102103xjo
class Parent extends React.Component {
constructor(props) {
super(props);
this.childTwo = React.createRef();
}
newUserCreated = () => {
this.childTwo.current.updateTable();
};
render() {
return (
<div className="App">
<ChildOne newUserCreated={this.newUserCreated} />
<ChildTwo ref={this.childTwo} />
</div>
);
}
}
class ChildOne extends React.Component {
handleSubmit = () => {
this.props.newUserCreated();
};
render() {
return <button onClick={this.handleSubmit}>Submit</button>;
}
}
class ChildTwo extends React.Component {
updateTable() {
console.log("Update Table");
}
render() {
return <div />;
}
}

Why is prevState argument null in calculateState method in Flux?

I set state in constructor this.state = {};, but prevState argument in calculateState method is null. Where should I set initial state of container?
class QuestionnairesContainer extends Component {
static getStores() {
return [QuestionnairesStore];
}
static calculateState(prevState) {
return {
questionnairesList: QuestionnairesStore.getState().questionnairesList,
pagingObject: prevState.pagingObject
};
}
constructor(props) {
super(props);
this.state = {
pagingObject: someData
};
}
render() {
return (
<section>
</section>
);
}
}
export default Container.create(QuestionnairesContainer);
I have found a solution on flux GitHub.
static calculateState(prevState) {
const init = prevState ? {} : {
pagingObject: someData,
};
return {
...init,
questionnairesList: QuestionnairesStore.getState().questionnairesList
};
}
constructor(props) {
super(props);
}

Resources