Reputation: 2134
Hello and thank you for your time:
I am following the following tutorial:https://app.pluralsight.com/library/courses/react-flux-building-applications/table-of-contents
And currently I have detected that when you try to create an author, it tries to load current's author's URL's author id. Because of it is being created, it is undefined, and so then the create author functionality does not work.
I have read some topics about checking undefined type both in JS and React: How to determine if variable is 'undefined' or 'null'?
Checking for Undefined In React
https://github.com/facebook/react/issues/3725
And I have tried the following:
In manageAuthorForm we pass in to the authorForm the author's state:
render() {
return (
<AuthorForm author={this.state.author}
onChange={this.setAuthorState}
onSave={this.saveAuthor}/>
);
};
And then I have tried into the AuthorForm:
import React from 'react';
import {Input} from "../common/textInput";
import Link from "react-router-dom/es/Link";
class AuthorForm extends React.Component {
componentWillReceiveProps(nextProps) {
if (nextProps.state.author === undefined) {
this.props.author = {
author: {
id: '',
firstName: '',
lastName: '',
}
};
}
}
render() {
return (
<form>
<h1>Manage author</h1>
<Input
name="firstName"
label="First Name"
value={this.props.author.firstName}
onChange={this.props.onChange}
/>
<Input
name="lastName"
label="Last Name"
value={this.props.author.lastName}
onChange={this.props.onChange}
/>
<button type="submit" value="Save" className="btn btn-default" onClick={this.props.onSave}><Link
to="/authors">Save
author</Link>
</button>
</form>
);
}
}
export {AuthorForm}
And it reports that nextProps are undefined:
Uncaught TypeError: Cannot read property 'author' of undefined
at AuthorForm.componentWillReceiveProps (authorForm.js:7)
at callComponentWillReceiveProps (react-dom.development.js:6389)
at updateClassInstance (react-dom.development.js:6575)
at updateClassComponent (react-dom.development.js:7848)
at beginWork (react-dom.development.js:8225)
at performUnitOfWork (react-dom.development.js:10224)
at workLoop (react-dom.development.js:10288)
at HTMLUnknownElement.callCallback (react-dom.development.js:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js:581)
at invokeGuardedCallback (react-dom.development.js:438)
at renderRoot (react-dom.development.js:10366)
at performWorkOnRoot (react-dom.development.js:11014)
at performWork (react-dom.development.js:10967)
at requestWork (react-dom.development.js:10878)
at scheduleWorkImpl (react-dom.development.js:10732)
at scheduleWork (react-dom.development.js:10689)
at scheduleTopLevelUpdate (react-dom.development.js:11193)
at Object.updateContainer (react-dom.development.js:11231)
at react-dom.development.js:15226
at Object.unbatchedUpdates (react-dom.development.js:11102)
at renderSubtreeIntoContainer (react-dom.development.js:15225)
at Object.render (react-dom.development.js:15290)
at Object../src/index.js (index.js:17)
at __webpack_require__ (bootstrap 78b34f0f34b98a41c613:678)
at fn (bootstrap 78b34f0f34b98a41c613:88)
at Object.0 (authorStore.js:39)
at __webpack_require__ (bootstrap 78b34f0f34b98a41c613:678)
at bootstrap 78b34f0f34b98a41c613:724
at bootstrap 78b34f0f34b98a41c613:724
componentWillReceiveProps @ authorForm.js:7
callComponentWillReceiveProps @ react-dom.development.js:6389
updateClassInstance @ react-dom.development.js:6575
updateClassComponent @ react-dom.development.js:7848
beginWork @ react-dom.development.js:8225
performUnitOfWork @ react-dom.development.js:10224
workLoop @ react-dom.development.js:10288
callCallback @ react-dom.development.js:542
invokeGuardedCallbackDev @ react-dom.development.js:581
invokeGuardedCallback @ react-dom.development.js:438
renderRoot @ react-dom.development.js:10366
performWorkOnRoot @ react-dom.development.js:11014
performWork @ react-dom.development.js:10967
requestWork @ react-dom.development.js:10878
scheduleWorkImpl @ react-dom.development.js:10732
scheduleWork @ react-dom.development.js:10689
scheduleTopLevelUpdate @ react-dom.development.js:11193
updateContainer @ react-dom.development.js:11231
(anonymous) @ react-dom.development.js:15226
unbatchedUpdates @ react-dom.development.js:11102
renderSubtreeIntoContainer @ react-dom.development.js:15225
render @ react-dom.development.js:15290
./src/index.js @ index.js:17
__webpack_require__ @ bootstrap 78b34f0f34b98a41c613:678
fn @ bootstrap 78b34f0f34b98a41c613:88
0 @ authorStore.js:39
__webpack_require__ @ bootstrap 78b34f0f34b98a41c613:678
(anonymous) @ bootstrap 78b34f0f34b98a41c613:724
(anonymous) @ bootstrap 78b34f0f34b98a41c613:724
And in the web browser it reports:
×
TypeError: Cannot read property 'author' of undefined
AuthorForm.componentWillReceiveProps
C:/Users/YonePC/WebstormProjects/flux/src/components/authors/authorForm.js:7
4 |
5 | class AuthorForm extends React.Component {
6 | componentWillReceiveProps(nextProps) {
> 7 | if (nextProps.state.author === undefined) {
8 | this.props.author = {
9 | author: {
10 | id: '',
View compiled
▶ 15 stack frames were collapsed.
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.
The full code, in github: https://github.com/YoneMoreno/ReactFluxAuthorsPageTutorial
Could you help me, please?
Thank you ;=)
Upvotes: 11
Views: 48282
Reputation: 674
const UndefinedCheck = data => {
if(data === undefined){
return 1
}else {
return data
}
}
export default UndefinedCheck
Upvotes: 0
Reputation: 2197
nextProps.state ?
The one that has a state it is the component, Please decide where are you going to handle the author
data. In the component props or in the state.
Besides that you should take a look of: https://www.npmjs.com/package/prop-types
Its a library for react to handle types and default values for your component props. With this library you are going to be able to do somethings like:
FunctionPointAutomatedTable.defaultProps = {
dataSource: [],
};
FunctionPointAutomatedTable.propTypes = {
applicationId: PropTypes.string,
functionType: PropTypes.string,
dataSource: PropTypes.array,
allowedTypes: PropTypes.array,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
onIgnore: PropTypes.func,
onMerge: PropTypes.func,
onUnmerge: PropTypes.func,
};
Upvotes: 0
Reputation: 997
Your error message is;
Cannot read property 'author' of undefined
It is actually not author
that is undefined but nextProps.state
. nextProps
is an object containing the contents of only the props.
The other problem here is that componentWillReceiveProps()
is not called when when mounting, thus if props.author
is initially undefined then that error handling won't work. Mayank Shukla has a good answer, however that requires you to have a constructor like so;
constructor(props) {
super(props);
this.state = {
author: this.props.author,
};
}
Since props cannot be updated, it makes more sense to put it in the state so that it can be in the future. If you need to receive prop updates, use setState()
in componentWillUpdate()
Another, more long winded solution would be to make author
a required prop, and not attempt to create that component until the necessary props exist. This is also better practice.
AuthorForm.propTypes = {
author: PropTypes.string.isRequired,
};
Upvotes: 2
Reputation: 104399
Simple solution will be:
<AuthorForm
author={this.state.author || {firstName:'', lastName:'', id:''}}
...
/>
And remove the componentWillReceiveProps
method from child component.
Better approach will be:
1- Either assign the initial value of author
in state as:
this.state = {
author: {firstName:'', lastName:'', id:''}
}
2- Or inside render method of child component, write it like this:
render(){
const {firstName='', lastName='', id=''} = this.props.author || {};
return(....)
}
And use firstName, lastName, id
directly instead of this.props.
Issues in your code:
1- It should be nextProps.author
instead of nextProps.state.author
in componentWillReceiveProps
lifecycle method.
2- Props are read-only, Whether you declare a component as a function or a class, it must never modify its own props. You are trying to change the value in componentWillReceiveProps
.
Upvotes: 7
Reputation: 1700
You should setUp default values to {this.state.author} which you set to component instead of setting default values to props into
Upvotes: 0