I'm building a quiz/survey builder, kind of CMS interface which will allow users to add as many questions as they want by clicking the type of question they want.
To start with, my state is set up in the App component as follow:
state = {
components: API.components,
comps: []
}
The admin screen has a selected number of buttons which will activate a question onClick. The question comes from the API.components. For example, we have: - Welcome Message - Thank You Message - Yes or No
/* 1. Generate a list of buttons with onClick props.addQuestion passing a fixed id via 'i' parameter */
const QuestionTypes = props => {
return (
<div data-name='typequestion'>
{props.details.map((el, i) => <div key={i}><button className="sm" onClick={() => props.addQuestion(i)}>{el.label}</button></div>)}
</div>
)
}
See Menu Questions screenshot: https://www.awesomescreenshot.com/image/3982311/8964261115690780c3f67d390ce08665
onClick, each of these buttons will trigger the 'addQuestion' method, which will pass a fixed ID (key) to the 'selectComponent' function to add the selected component to the comps[] array:
/* onClick, a method 'addQuestion' is called */
/* This method will setState and call a function selectComponent passing a key (id) in order to select the correct component */
addQuestion = key => {
this.setState({
comps: [...this.state.comps, this.selectComponent(key)]
});
}
The selectComponent function has a switch to pass the correct component:
selectComponent = (key) => {
switch(key) {
case 0:
return <WelcomeMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
case 1:
return <ThankYouMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
case 2:
return <YesNo details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
default:
return 'Please select a component from the left side menu'
}
}
This will add an element to comps[] array:
[
0: {element here ..}
1: {element here ..} etc.
]
Here an example of the code for the component:
const ThankYouMessage = props => (
<section className="ui-component-view" data-name="thankyou">
<img src={ThankYouImage} alt="x" />
<h3>Thanks for completing our form!</h3>
<div>
<DeleteButton deleteQuestion={props.deleteQuestion} />
</div>
</section>
);
See Selected Welcome Message Component screenshot: https://www.awesomescreenshot.com/image/3982315/f59e1bf79a31194aa3ee3ad2467658a0
PROBLEM:
As you can see, each component will have a delete button. While each component is added to the array without issues, I can't find a way to delete ONLY the selected component when I click the delete button.
I've tried to use .filter(), splice() but I don't have the right index for the newly created or updated array list. I want to use the React way to do it, not jQuery or Javascript-ish.
Example of Delete Button. Please note that the props.index is passing the original clicked button id (key), which will not match the newly comps[] array index:
const DeleteButton = props => (
<span className="deleteButton" onClick={() => props.deleteQuestion(props.index)}>×<small>Delete</small></span>
);
export default DeleteButton;
Here the Delete method:
deleteQuestion = e => {
const comps = [...this.state.comps]
// 2. here I need to add something that will DELETE ONLY the clicked button index for that component
// 3. Update state
this.setState({ comps });
}
Please see the full code for the App component: class App extends React.Component {
state = {
components: API.components,
comps: [],
multichoice: {}
}
selectComponent = (key) => {
switch(key) {
case 0:
return <WelcomeMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
case 1:
return <ThankYouMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
case 2:
return <YesNo details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
break;
default:
return 'Please select a component from the left side menu'
}
}
addQuestion = key => {
this.setState({
comps: [...this.state.comps, this.selectComponent(key)]
});
}
deleteQuestion = e => {
const comps = [...this.state.comps]
// 2. here I need to add something that will DELETE ONLY the component related to the delete button
// 3. Update state
this.setState({ comps });
}
render() {
return (
<Container>
<Row>
<Col>
<h1>Survey Builder </h1>
</Col>
</Row>
<Row>
<Col lg={3} className="border-right">
<QuestionTypes addQuestion={this.addQuestion} details={this.state.components} />
</Col>
<Col lg={9}>
<Row>
<Col lg={12}>
<QuestionEdit comps={this.state.comps} details={this.state.components} />
</Col>
</Row>
</Col>
</Row>
</Container>
)
}
}
export default App;