Edit action in react-redux - reactjs

I am trying to perform an edit action in react-redux. First, I created a button on the index page.
<Link to = {`/standups/${list.id}`}>Edit</Link>
When I clicked on this button, it went to the edit page but no data was present.
In my edit page, I have this code:
class StandupEdit extends Component {
constructor(props){
super(props);
this.state = {
standups: {
user_id: this.props.standup ? this.props.standup.user_id : '',
day: this.props.standup ? this.props.standup.day : '',
work_done: this.props.standup ? this.props.standup.work_done : '',
work_planned: this.props.standup ? this.props.standup.work_planned : '',
blocker: this.props.standup ? this.props.standup.blocker : ''
},
submitted: false
};
}
handleSubmit = (event) => {
event.preventDefault();
const { standups } = this.state;
const { dispatch } = this.props;
if(standups.work_done && standups.work_planned && standups.blocker) {
dispatch(addStandup(this.state.standups))
} else {
this.setState({
submitted: true
})
}
}
componentWillReceiveProps = (nextProps) => {
debugger
this.setState({
standups: {
user_id: nextProps.user_id,
day: nextProps.day,
work_done: nextProps.work_done,
work_planned: nextProps.work_planned,
blocker: nextProps.blocker
}
});
}
componentDidMount(){
if(this.props.match.params.id){
this.props.editStandup(this.props.match.params.id)
}
}
handleChange = (event) => {
const {name, value} = event.target;
const {standups} = this.state;
this.setState({
standups: {
...standups,
[name]: value
}
});
}
render() {
const {standups, submitted, fireRedirect} = this.state
return (
<MuiThemeProvider theme={theme}>
<Paper>
<h1 className='header'>Add new standup</h1>
</Paper>
<Grid container spacing={16}>
<form onSubmit={this.handleSubmit}>
<Paper className='form'>
<TextField fullWidth name= "work_done"
value = {standups.work_done}
onChange= {this.handleChange}
type= "text"
placeholder= "What did you work on yesterday?"/>
{
submitted && !standups.work_done ?
<p>Work done is required</p> : ''
}
</Paper>
<Paper className='form'>
<TextField fullWidth name= "work_planned"
value = {standups.work_planned}
onChange= {this.handleChange}
type= "text"
placeholder= "What are you planning to work on today?"/>
{
submitted && !standups.work_planned ?
<p>Work planned is required</p> : ''
}
</Paper>
<Paper className='form'>
<TextField fullWidth name= "blocker"
value = {standups.blocker}
onChange= {this.handleChange}
type= "text"
placeholder= "Any impediments in your way?"/>
{
submitted && !standups.blocker ?
<p>Blocker required</p> : ''
}
</Paper>
<div className='button'>
<Button type="submit">Update</Button>
</div>
</form>
</Grid>
</MuiThemeProvider>
);
}
}
function mapStateToProps(state, props){
if (props.match.params.id) {
return {
standup: state.standup.standups.findIndex(item => item.id === props.match.params.id)
}
}
return {
standup: null
}
}
export default connect(mapStateToProps, {editStandup})(StandupEdit);
In action, I have this code:
export function editStandup(id) {
return dispatch => {
axios(`${ROOT_URL}/standups/${id}/${API_KEY}`, {
headers: authHeader(),
method: 'GET',
}).then( response => {
dispatch(success(response.data.standup))
})
}
function success(response) {
return {
type: 'STANDUP_EDIT',
payload: response
}
}
}
export function updateStandup(standup) {
const request = axios({
headers: authHeader(),
method: 'PUT',
url: `${ROOT_URL}/standups${API_KEY}`,
data: standup
})
return {
type: 'STANDUP_UPDATE',
payload: request
}
}
And I have following code in my reducer:
export function standup(state = {}, action){
switch (action.type) {
case 'STANDUP_UPDATE':
return state.map(item => {
if(item.id === action.payload.id)
return
standup: action.payload
return item;
});
case 'STANDUP_EDIT':
const index = state.standups.findIndex(item => item.id === action.payload.id);
if (index > -1){
return state.standups.map(item => {
if(item.id === action.payload.id)
return action.payload
});
}else{
return
standup: action.payload
}
default:
return state;
}
}
In my reducer findIndex(item => item.id === action.payload.id);, item => item.id contain error item.id is undefined.
Will anyone help me in solving this problem?

You aren't updating the state in reducer correctly, standups is not defined initially which you must do. Check the same code below
export function standup(state = {standups: []}, action){
switch (action.type) {
case 'STANDUP_UPDATE': {
const index = state.standups.findIndex(item => item.id === action.payload.id);
return {
...state,
standups: {
...state.standups.slice(0, index),
action.payload,
...state.standups.slice(index + 1),
}
}
}
case 'STANDUP_EDIT':
const index = state.standups.findIndex(item => item.id === action.payload.id);
if (index > -1){
return {
...state,
standups: {
...state.standups.slice(0, index),
action.payload,
...state.standups.slice(index + 1),
}
}
}
return {
...state,
standups: {
...state.standups
action.payload,
}
default:
return state;
}
}
Also your component name is StandupEdit and you are connecting StandupNew with the connect function
export default connect(mapStateToProps, {editStandup})(StandupEdit);

Related

Iam making a Todo using (useReducer and useContext) but the update functionality is not working please check this out

This is my App.jsx , where iam displaying all the todos, after clicking edit the input gets the value of selected todo and while changing the value and clicking on update it does nothing.
export default function App() {
const { dispatch, state } = useContext(todoContext);
const [todo, setTodo] = useState("");
const [isEditing, setIsEditing] = useState(false);
const [selectedTodo, setSelectedTodo] = useState("");
const handleSubmit = (e) => {
const id = uuidv4();
e.preventDefault();
if (!isEditing) {
dispatch({
type: "ADD_TODO",
payload: { id: id, text: todo },
});
setTodo("");
} else {
dispatch({
type: "UPDATE_TODO",
payload: selectedTodo,
});
setIsEditing(false);
setTodo("");
}
};
const handleEdit = (val) => {
setIsEditing(true);
const item = state.todos.find((todo) => todo.id === val.id);
setTodo(item.text);
setSelectedTodo(item);
};
return (
<div className="App">
<br />
<h1>Hello World This is Todo App</h1>
<br />
<form onSubmit={handleSubmit}>
<input
value={todo}
onChange={(e) => setTodo(e.target.value)}
type="text"
placeholder="Enter a todo"
/>
<button>{isEditing ? "Update" : "Submit"}</button>
</form>
{state.todos.map((item) => (
<div key={item.id} className="todoitem">
<p
onClick={() => dispatch({ type: "TOGGLE_TODO", payload: item.id })}
style={{
cursor: "pointer",
textDecoration: item.completed ? "line-through" : "",
}}
>
{item.text}
</p>
<span
onClick={() => dispatch({ type: "REMOVE_TODO", payload: item.id })}
>
×
</span>
<button onClick={() => handleEdit(item)}>Edit</button>
</div>
))}
</div>
);
}
This is my reducers (todoReducer.jsx) , where the upadte functionality doesnot work when i click edit to change the value and click update it does nothing
export const INITIAL_STATE = {
todos: [],
updated: [],
};
export const reducer = (state, action) => {
switch (action.type) {
case "ADD_TODO":
return {
...state,
todos: [...state.todos, action.payload],
};
case "REMOVE_TODO": {
return {
...state,
todos: state.todos.filter((item) => item.id !== action.payload),
};
}
case "TOGGLE_TODO":
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
),
};
case "UPDATE_TODO":
return {
...state,
todos: state.todos.map((todo) => {
if (todo.id === action.payload.id) {
return action.payload;
}
return todo;
}),
};
default:
return state;
}
};
you need to update text with latest text
selectedTodo has old data
todo have new text
in your handleSubmit please update below code
dispatch({
type: "UPDATE_TODO",
payload: { ...selectedTodo, text: todo },
});

Access to api response data

My code pass in a search term and the promise api call returns one record and the data format is as below:
` json api data
0:
{
id:"aff3b4fa-bdc0-47d1-947f-0163ff5bea06"
keyword: somekeyword
URL:"mypage.html"
}
I need to retrieve the URL value, so I try to get URL by using response.data[0].URL. But I receive the error "Unhandled Rejection (TypeError): response.data[0] is undefined". How do I get the URL value? Thanks.
` autocomplete.js
export class Autocomplete extends Component {
state = {
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: "",
suggestions: [],
results: [],
URL: "",
};
componentDidMount() {
this.GetPrograms();
const { userInput } = this.state;
//this.runSearch();
}
GetPrograms = () => {
axios
.get("https://mydomain/GetPrograms/")
.then((response) => {
this.setState({ suggestions: response.data });
});
};
runSearch = async () => {
const response = await axios.get(
"https://mydomain/api/get",
{
params: {
searchTerm: this.state.userInput,
},
}
);
let results = response.data;
console.log("response", results);
this.setState({ results: results, URL: response.data[0].URL });
window.location.href =
"https://mydomain/" + this.state.URL;
};
onChange = (e) => {
const { suggestions } = this.state; //this.props;
const userInput = e.currentTarget.value;
const filteredSuggestions = suggestions.filter(
(suggestion) =>
suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value,
});
};
onClick = (e) => {
this.setState({
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: e.currentTarget.innerText,
});
this.onSearch();
console.log(
"child component clicked and value=" + e.currentTarget.innerText
);
};
onKeyDown = (e) => {
const { activeSuggestion, filteredSuggestions } = this.state;
if (e.keyCode === 13) {
this.setState({
activeSuggestion: 0,
showSuggestions: false,
userInput: filteredSuggestions[activeSuggestion],
});
} else if (e.keyCode === 38) {
if (activeSuggestion === 0) {
return;
}
this.setState({ activeSuggestion: activeSuggestion - 1 });
} else if (e.keyCode === 40) {
if (activeSuggestion - 1 === filteredSuggestions.length) {
return;
}
this.setState({ activeSuggestion: activeSuggestion + 1 });
}
//this.setState({ searchTerm: e.currentTarget.value });
console.log("userinput:" + this.state.userInput);
};
render() {
const {
onChange,
onClick,
onKeyDown,
onKeyPress,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput,
},
} = this;
let suggestionsListComponent;
if (showSuggestions && userInput) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul class="suggestions">
{filteredSuggestions.map((suggestion, index) => {
let className;
if (index === activeSuggestion) {
className = "";
}
return (
<li key={suggestion} onClick={onClick}>
{suggestion}
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div class="no-suggestions">
<em>No suggestions</em>
</div>
);
}
}
return (
<div>
<input
id="search-box"
placeholder="Search..."
type="search"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
/>
{suggestionsListComponent}
</div>
);
}
}
export default Autocomplete;
`
The api call returns 0 record that causes the error.

React redux update nested Object property value

I'm try to make fields validation in mine project and here is mine fields state model
const initialState = {
fields: {
title: {
value: '',
isCorrectValue: false
},
amount: {
value: '',
isCorrectValue: false
}
}
}
I'm trying to update mine field state isCorrectValue if value.length lower then 1 here is regex what I'm using to check fields value length
const checkValue = (value) => {
return (/^.{1,}$/).test(value);
};
here is mine reducer where I'm trying to update mine state cannot understand why i cannot to grasp
isCorrectValue
export default function fieldsReducer(state = initialState, action) {
switch (action.type) {
case ONCHANGE:
return {
...state,
fields: {
...state.fields,
[`${action.payload.name}`]: {
...[`${action.payload.name}`],
value: action.payload.value
}
}
}
case VALIDATEFIELDS:
return {
...state,
fields: Object.keys(state.fields).reduce((acc, curr) => {
!checkTitle(state.fields[curr].value)
? Object.assign(acc, state.fields,
{
curr: { ...state.fields, [state.fields[curr].isCorrectValue]: !state.fields[curr].isCorrectValue }
}
)
: acc = state.fields;
return acc;
}, {})
}
default: return state;
}
}
here is mine component where reducer is working
const AddTransaction = () => {
const state = useSelector(state => state.fieldsReducer);
const dispatch = useDispatch();
console.log(state.fields.title.isCorrectValue)
return (
<div className='add-transaction-wrapper'>
<div className='add-expense-inputs-wrapper'>
<TextField
id='title'
label='title'
value={state.fields.title.value}
onChange={e => dispatch(onHandleChange(e, e.target.id))}
/>
<TextField
id="amount"
label="expense amount"
type="number"
InputLabelProps={{
shrink: true,
}}
value={state.fields.amount.value}
onChange={e => dispatch(onHandleChange(e, e.target.id))}
error={state.fields.amount.isCorrectValue}
/>
<button onClick={() => dispatch(fieldsValidation())}>click</button>
</div>
</div>
)
}
You can try the following in your reducer:
//not part of your reducer
const state = {
fields: {
title: {
value: '',
isCorrectValue: false
},
amount: {
value: '',
isCorrectValue: false
}
}
}
//just a sample action
const action = {
payload:{
name:'amount',
value:true
}
}
//this is what you should do in your reducer
const newState = {
...state,
fields: {
...state.fields,
[action.payload.name]: {
...state.fields[action.payload.name],
value: action.payload.value
}
}
}
console.log('new state:',newState)
VALIDATEFIELDS is kind of a mess and I have no idea what you want to do there.

How to change the background color

I am new to React and It really interesting to work on it. As per my current application which is a Quiz app, If user selects any of the options it should change the background color to red or green. I am using the semantic UI and to the menu item, I am passing the data with an on-click event where I am storing the selected answer from the user. But I am unable to change the color wrt the correct answer or wrong answer. Here is the code.
import React, { Component } from 'react';
import {
Container,
Segment,
Item,
Divider,
Button,
Icon,
Message,
Menu,
Header
} from 'semantic-ui-react';
import Swal from 'sweetalert2';
import Loader from '../Loader';
import Countdown from '../Countdown';
import Result from '../Result';
import Offline from '../Offline';
import he from 'he';
import { getRandomNumber } from '../../utils/getRandomNumber';
class Quiz extends Component {
constructor(props) {
super(props);
this.state = {
quizData: null,
isLoading: true,
questionIndex: 0,
correctAnswers: 0,
userSlectedAns: null,
quizIsCompleted: false,
questionsAndAnswers: [],
isOffline: false,
bgColor: ""
};
this.timeTakesToComplete = undefined;
this.setData = this.setData.bind(this);
this.handleItemClick = this.handleItemClick.bind(this);
this.handleNext = this.handleNext.bind(this);
this.timesUp = this.timesUp.bind(this);
this.timeAmount = this.timeAmount.bind(this);
this.renderResult = this.renderResult.bind(this);
this.retakeQuiz = this.retakeQuiz.bind(this);
this.startNewQuiz = this.startNewQuiz.bind(this);
this.resolveError = this.resolveError.bind(this);
}
componentDidMount() {
const { API } = this.props;
fetch(API)
.then(respone => respone.json())
.then(result => setTimeout(() => this.setData(result.results), 1000))
.catch(error => setTimeout(() => this.resolveError(error), 1000));
}
resolveError(error) {
if (!navigator.onLine) {
this.setState({ isOffline: true });
console.log('Connection problem');
} else {
this.setState({ isOffline: true });
console.log('API problem ==> ', error);
}
}
setData(results) {
if (results.length === 0) {
const message =
"The API doesn't have enough questions for your query<br />" +
'(ex. Asking for 50 questions in a category that only has 20).' +
'<br /><br />Please change number of questions, difficulty level ' +
'or type of questions.';
return Swal.fire({
title: 'Oops...',
html: message,
type: 'error',
timer: 10000,
onClose: () => {
this.props.backToHome();
}
});
}
const quizData = results;
const { questionIndex } = this.state;
const outPut = getRandomNumber(0, 3);
const options = [...quizData[questionIndex].incorrect_answers];
options.splice(outPut, 0, quizData[questionIndex].correct_answer);
this.setState({ quizData, isLoading: false, options, outPut });
}
handleItemClick(e, { name }) {
const {
userSlectedAns,
quizData,
questionIndex,
} = this.state;
this.setState({ userSlectedAns: name });
console.log(name);
if (userSlectedAns === he.decode(quizData[questionIndex].correct_answer)) {
this.state.active = 'green';
}
}
handleNext() {
const {
userSlectedAns,
quizData,
questionIndex,
correctAnswers,
questionsAndAnswers
} = this.state;
let point = 0;
if (userSlectedAns === he.decode(quizData[questionIndex].correct_answer)) {
point = 1;
}
questionsAndAnswers.push({
question: he.decode(quizData[questionIndex].question),
user_answer: userSlectedAns,
correct_answer: he.decode(quizData[questionIndex].correct_answer),
point
});
if (questionIndex === quizData.length - 1) {
this.setState({
correctAnswers: correctAnswers + point,
userSlectedAns: null,
isLoading: true,
quizIsCompleted: true,
questionIndex: 0,
options: null,
questionsAndAnswers
});
return;
}
const outPut = getRandomNumber(0, 3);
const options = [...quizData[questionIndex + 1].incorrect_answers];
options.splice(outPut, 0, quizData[questionIndex + 1].correct_answer);
this.setState({
correctAnswers: correctAnswers + point,
questionIndex: questionIndex + 1,
userSlectedAns: null,
options,
outPut,
questionsAndAnswers
});
}
timesUp() {
this.setState({
userSlectedAns: null,
isLoading: true,
quizIsCompleted: true,
questionIndex: 0,
options: null
});
}
timeAmount(timerTime, totalTime) {
this.timeTakesToComplete = {
timerTime,
totalTime
};
}
renderResult() {
setTimeout(() => {
const { quizData, correctAnswers, questionsAndAnswers } = this.state;
const { backToHome } = this.props;
const resultRef = (
<Result
totalQuestions={quizData.length}
correctAnswers={correctAnswers}
timeTakesToComplete={this.timeTakesToComplete}
questionsAndAnswers={questionsAndAnswers}
retakeQuiz={this.retakeQuiz}
backToHome={backToHome}
/>
);
this.setState({ resultRef, questionsAndAnswers: [] });
}, 2000);
}
retakeQuiz() {
const { quizData, questionIndex } = this.state;
const outPut = getRandomNumber(0, 3);
const options = [...quizData[questionIndex].incorrect_answers];
options.splice(outPut, 0, quizData[questionIndex].correct_answer);
this.setState({
correctAnswers: 0,
quizIsCompleted: false,
startNewQuiz: true,
options,
outPut
});
}
startNewQuiz() {
setTimeout(() => {
this.setState({ isLoading: false, startNewQuiz: false, resultRef: null });
}, 1000);
}
render() {
const {
quizData,
questionIndex,
options,
userSlectedAns,
isLoading,
quizIsCompleted,
resultRef,
startNewQuiz,
isOffline
// outPut,
// correctAnswers,
} = this.state;
// console.log(userSlectedAns);
// console.log(questionIndex, outPut);
// console.log('Score ==>', correctAnswers);
if (quizIsCompleted && !resultRef) {
this.renderResult();
// console.log('Redirecting to result');
}
if (startNewQuiz) {
this.startNewQuiz();
}
return (
<Item.Header>
{!isOffline && !quizIsCompleted && isLoading && <Loader />}
{!isOffline && !isLoading && (
<Container>
<Segment>
<Item.Group divided>
<Item>
<Item.Content>
<Item.Extra>
<Header as="h1" block floated="left">
<Icon name="info circle" />
<Header.Content>
{`Question No.${questionIndex + 1} of ${
quizData.length
}`}
</Header.Content>
</Header>
<Countdown
countdownTime={this.props.countdownTime}
timesUp={this.timesUp}
timeAmount={this.timeAmount}
/>
</Item.Extra>
<br />
<Item.Meta>
<Message size="huge" floating>
<b>{`Q. ${he.decode(
quizData[questionIndex].question
)}`}</b>
</Message>
<br />
<Item.Description>
<h3>Please choose one of the following answers:</h3>
</Item.Description>
<Divider />
<Menu vertical fluid size="massive">
{options.map((option, i) => {
let letter;
switch (i) {
case 0:
letter = 'A.';
break;
case 1:
letter = 'B.';
break;
case 2:
letter = 'C.';
break;
case 3:
letter = 'D.';
break;
default:
letter = i;
break;
}
const decodedOption = he.decode(option);
return (
<Menu.Item
key={decodedOption}
name={decodedOption}
active={userSlectedAns === decodedOption}
onClick={this.handleItemClick}
// style={{backgroundColor: this.state.bgColor }}
>
<b style={{ marginRight: '8px' }}>{letter}</b>
{decodedOption}
</Menu.Item>
);
})}
</Menu>
</Item.Meta>
<Divider />
<Item.Extra>
<Button
primary
content="Next"
onClick={this.handleNext}
floated="right"
size="big"
icon="right chevron"
labelPosition="right"
disabled={!userSlectedAns}
/>
</Item.Extra>
</Item.Content>
</Item>
</Item.Group>
</Segment>
<br />
</Container>
)}
{quizIsCompleted && !resultRef && (
<Loader text="Getting your result." />
)}
{quizIsCompleted && resultRef}
{isOffline && <Offline />}
</Item.Header>
);
}
}
export default Quiz;
I checked your handleItemClick function and found that you're mutating the state directly. You should use setState() to update the state, that's the basic thing about React's state mutation.
Please change the following:
if (userSlectedAns === he.decode(quizData[questionIndex].correct_answer)) {
this.state.active = 'green';
}
To this way:
if (userSlectedAns === he.decode(quizData[questionIndex].correct_answer)) {
this.setState({
active: 'green'
});
}

How do I manage this form in redux?

I'm building an online store and I'm creating a form where the user will select an option and the option's price will be added to the total price
class SingleProduct extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
var products = this.props.products.products;
var ID = this.props.router.location.pathname.slice(9, 100)
var productArray = this.props.products.products.data.filter(function(product) {
return product.id === ID;
})
var product = productArray[0];
var addToCart = (id, options) => {
this.props.dispatch((dispatch) => {
if(this.props.value == 'select'){
this.props.product.options = 0;
}
else if(this.state.value == 'no-edge'){
this.props.product.options = 0;
}
else if(this.state.value == '2inchHemOnly'){
this.props.product.options = 20;
}
else if(this.state.value == '2inchHG'){
this.props.product.options = 25;
}
else if(this.state.value == 'HandG'){
this.props.product.options = 30;
}
else if(this.state.value == 'rope-rail'){
this.props.product.options = 35;
}
else if(this.state.value == 'pole-pocket'){
this.props.product.options = 40;
}
var values = this.props.product.values;
var options = this.props.product.options;
api.AddCart(id, this.props.product.quantity)
.then((options) => {
console.log(options)
dispatch({type: "Update_Options", payload: options})
})
.then((values) => {
console.log(values)
dispatch({type: "Update_Value", payload: values})
})
.then((cart) => {
console.log(cart)
dispatch({type: "Cart_Updated", gotNew: false})
})
.then(() => {
dispatch({type: "Fetch_Cart_Start", gotNew: false})
api.GetCartItems()
.then((cart, options, values) => {
dispatch({type: "Fetch_Cart_End", payload: cart, gotNew: true})
dispatch({type: "Update_Options", payload: options})
dispatch({type: "Update_Value", payload: values})
})
})
.then(() => {
console.error(options)
})
.catch((e) => {
console.log(e)
})
})
}
addToCart(product.id);
}
return (
<main role="main" id="container" className="main-container push">
<section className="product">
<div className="content">
<div className="product-listing">
<div className="product-description">
<p className="price"><span className="hide-content">Unit price </span>{'$' + product.meta.display_price.with_tax.amount/100 + this.props.product.options}</p>
<form className="product" onSubmit={this.handleSubmit.bind(this)}>
<label>SELECT EDGING OPTION</label>
<select name="edging" value={this.state.value} onChange={this.handleChange}>
<option value="select">-- Please select --</option>
<option value="no-edge">No Edge</option>
<option value="2inchHemOnly">2” Hem Only</option>
<option value="2inchHG">2” Hem and Grommets 24” On Center</option>
<option value="HandG">Hem and Grommets 12” on Center</option>
</select>
<div className="quantity-input" style={style}>
<p className="hide-content">Product quantity.</p>
<button type="submit" className="submit">Add to cart</button>
</form>
</div>
</div>
</section>
<MailingList />
</main>
)
}
}
export default connect(mapStateToProps)(SingleProduct);
And here is my reducer:
const initialState = {
quantity: 1,
options: 0,
values: [
{ value: '-- Please select --' },
{ value: 'No Edge' },
{ value: '2” Hem Only' },
{ value: 'No Edge' },
{ value: '2” Hem and Grommets 24” On Center' },
{ value: 'Hem and Grommets 12” on Center' }
]
}
const ProductReducer = (state=initialState, action) => {
switch (action.type) {
case "Update_Quantity": {
return {...state, quantity: action.payload};
}
case "Update_Options": {
return {...state,
options: action.payload};
}
case "Update_Value": {
return {...state,
value: action.payload};
}
default: {
return {...state};
}
}
};
export default ProductReducer;
When I add to the cart my 'value' is undefined. And on refresh, 'options' goes back to 0. My quantity stays in the state though. I just don't know why this is happening.
The react docs state: Whether you declare a component as a function or a class, it must never modify its own props.
Therefore, you might want to make a copy of the props into a variable and then modify the copy. One way to do this might be to place this line:
let propsCopy = { ...this.props }
above the line var addToCart = (id, options) => {
and then use propsCopy in place of props in the subsequent lines.

Resources