I am stuck on same bug for 2 days now and I can t find fix. I was hoping somebody would help me out with this one. It seems that error is on form: PropTypes.array.isRequired, in PropTypes but I don t get why. I mean I initialized state to empty array in formReducer. I would appreciate any help cause I just started Learning React and React-Redux is a bit overwhelming for me but I really want to learn it.
loginPage
import React from "react";
import { connect } from "react-redux";
import * as formAction from "../../redux/actions/formAction";
import PropTypes from "prop-types";
class LoginPage extends React.Component {
constructor() {
super();
this.state = {
visitor: {
username: "",
password: "",
},
};
//this.updateVisitor = this.updateVisitor.bind(this);
}
updateVisitor(attr, event) {
console.log(attr + " == " + event.target.value);
const updatedVisitor = { ...this.state.visitor }; //ili je object assign vrati se na 27.47
updatedVisitor[attr] = event.target.value;
this.setState({
visitor: updatedVisitor,
});
}
register(event) {
event.preventDefault();
this.props.dispatch(formAction.insertID(this.state.visitor));
console.log("REGISTER:" + JSON.stringify(this.state.visitor));
}
login(event) {
event.preventDefault();
console.log("LOGIN:" + JSON.stringify(this.state.visitor));
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<h1>Register</h1>
<form onSubmit={this.register.bind(this)}>
<input
onChange={this.updateVisitor.bind(this, "username")}
className="form-control"
type="text"
placeholder="Username"
></input>
<br />
<input
onChange={this.updateVisitor.bind(this, "password")}
className="form-control"
type="password"
placeholder="Password"
></input>
<br />
<button type="submit" value="save">
Register
</button>
</form>
<hr />
<h1>Login</h1>
<form onSubmit={this.login.bind(this)}>
<input
onChange={this.updateVisitor.bind(this, "username")}
className="form-control"
type="text"
placeholder="Username"
></input>
<br />
<input
onChange={this.updateVisitor.bind(this, "password")}
className="form-control"
type="password"
placeholder="Password"
></input>
<br />
<button type="submit" value="save">
Log in
</button>
{this.props.form.map((Zasvaki) => (
<div key={Zasvaki.username}>{Zasvaki.username}</div>
))}
</form>
</div>
</div>
</div>
);
}
}
LoginPage.propTypes = {
dispatch: PropTypes.func.isRequired,
form: PropTypes.array.isRequired,
};
function mapStateToProps(state) {
return {
form: state.form,
};
}
export default connect(mapStateToProps)(LoginPage);
configureStore
import rootReducer from "./reducers/formReducer";
import reduxImmutableStateInvariant from "redux-immutable-state-invariant";
export default function configureStore(initialState) {
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; //Add support for redux devtools
return createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(reduxImmutableStateInvariant()))
);
}
formAction
export function insertID(ID) {
return { type: "INSERT_ID", ID: ID };
}
formReducer
switch (action.type) {
case "INSERT_ID":
return [...state, { ...action.ID }]; //Vraca klonirani array sa svim prijasnjim stanima plus sa novim stanjem dodanim
default:
return state;
}
}
index.js //Combine reducer
import form from "./formReducer";
const rootReducer = combineReducers({
form: form,
});
export default rootReducer;
So the reducer doesn't have name in your case, so when you assing values to the form just assign the whole state:
function mapStateToProps(state) {
console.log("there's no 'form' on the state: ", state.form); // undefined
// looks like you need to assign whole state
return { form: state };
}
and now you wont need to do this.props.form &&
part in:
this.props.form && this.props.form.map((Zasvaki) => (
^^ that would fix your error, BUT what I really suggest you doing is to make redux state an object and actually assign the value you want to a property form
in your case. So in reducer you will have something like this:
export default function formReducer(state = {}, action) {
switch (action.type) {
case "INSERT_ID":
return {
...state,
form: {
...action.ID
}
}
default:
return {
...state
}
}
}
Then in loginPage.js you would need following changes:
Auth.propTypes = {
dispatch: PropTypes.func.isRequired,
// most likely you will not need an array of user names and passwords
// change back to the array if otherwise
form: PropTypes.shape({
username: PropTypes.string,
password: PropTypes.string,
}),
};
function mapStateToProps(state) {
return { form: state.form };
}
export default connect(mapStateToProps)(Auth);
and in the html just display properties of the form
you want to see:
{this.props.form && (
<div key={this.props.form.username}>{this.props.form.password}</div>
)}