Reputation: 1235
This is similar to a previous question I had asked before, but I have since moved my project architecture around to include Redux.
I have a component that dynamically generates it's dropdown contents based on a data response that's currently coming from within the app.
One of the dropdowns features a selection of none, 1, 5, 13 items
. Based on which number the user selects a second section should dynamically render showing that many rows with their own dropdown.
The problem I'm having is that I originally controlled this behavior by using local state and react hooks. Since then the dropdown options have moved to the store and I can no longer add the the onChange behavior to each unique option now that they are being generated as part of a map function.
Here's the original CodeSandbox for local state:
And this is what my current select drop down looks like from my application now that it's reading from the store:
<Select
onChange={e => {
props.updateCart(
{
lineOne: 'Thing#1',
lineTwo: 'addOns',
itemThree: 'Thing#3',
item:
parent.configurationItems[parseInt(e.target.value, 10)]
},
)
}}
>
{parent.configurationItems.map((obj, idx) => {
const { id, name } = obj
return (
<option
key={id}
value={idx}
>
{name}
</option>
)
})}
</Select>
</Col>
Upvotes: 0
Views: 79
Reputation: 15688
Made a sandbox for you that accomplishes what you're trying to do with redux: https://codesandbox.io/s/bj984
This is your updated ConfigurationOptions
component, see sandbox for the rest of the code :)
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import "antd/dist/antd.css";
import { Row, Col } from "antd";
import AntCollapse from "./CustomCollapse";
import { connect } from "react-redux";
import { setNumberInRedux } from "./configActions";
const Button = styled.button`
color: white;
background-color: #0076de;
border-radius: 5px;
`;
const ConfigurationOptions = ({ config, setNumberInRedux }) => {
const [configNumber, setConfigNumber] = useState(0);
const [configList, setConfigList] = useState([]);
const setConfig = number => {
setConfigNumber(number); //change component-state
setNumberInRedux(number); //call action-creator to update redux
};
//will only run when there is a change to the redux state
useEffect(() => {
const number = config.number;
//set list when redux state number changes
let newArray = new Array(parseInt(number, 10)).fill(0);
setConfigList(newArray);
}, [config]);
const setList = (number, index) => {
setConfigList(prevState => {
let newState = [...prevState];
newState[index] = parseInt(number, 10);
return newState;
});
};
return (
<AntCollapse header="configuration test">
<div>
<h1>Section Header</h1>
<Row>
<Col span={4} offset={20}>
<Button type="submit">Apply to All</Button>
</Col>
</Row>
<Row>
<Col span={12}>
<h3>Config Section #1</h3>
</Col>
</Row>
<Row>
<Col span={12}>
<p>How many do you need?</p>
</Col>
<Col span={4} offset={8}>
<select
value={configNumber}
onChange={e => setConfig(e.target.value)}
>
<option value={0}>None</option>
<option value={1}>1 Option</option>
<option value={5}>5 Options</option>
<option value={13}>13 Options</option>
</select>
</Col>
</Row>
<Row>
<Col span={12}>
<h3>Conditional Config Section</h3>
</Col>
</Row>
{configList.map((num, i) => (
<Row key={i.toString()}>
<Col span={12}>
<p>Option Configuration Dropdown</p>
</Col>
<Col span={4} offset={8}>
<select value={num} onChange={e => setList(e.target.value, i)}>
<option value={0}>Default</option>
<option value={1}>Add #1</option>
<option value={2}>Add #2</option>
<option value={3}>Add #3</option>
</select>
</Col>
</Row>
))}
</div>
</AntCollapse>
);
};
const mapStateToProps = state => {
return {
config: state.config
};
};
const mapDispatchToProps = dispatch => {
return {
setNumberInRedux: number => {
dispatch(setNumberInRedux(number));
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(ConfigurationOptions);
Upvotes: 1