I have a reactJs accordion in which i display questions and answers (faq), each question may have multiple answers, the data is fetched from an api with axios, i have two forms to post questions and answers, the question's form works as i want, but the answer's form does not, the issue is that i need the selected question's ID so i can pass it as a parameter to the url in axios ('https://api.com/answers?question_id='+param.question_id) so i can post the answer in the correct question. In each question i have a button Answer this question the click should get the question ID so i can add it to the state
I have this state in the App.js
class App extends Component {
constructor(props) {
super(props);
this.conteneur = React.createRef();
this.state = {
questions: [],
question_id: null
params: {
client_id: null,
question_id: null
},
};
}
handleSentData = (dataQ) => {
this.sendData(dataQ);
}
sendData = (formData) => {
let newData = { ...this.state };
newData.params = {
client_id: this.props.client,
question_id: this.state.theQuestion,
name : formData.name,
email : formData.email,
subject : formData.answer
};
Api.answerQ(newData.params)
.then((response) => {
if (response.data.status === "success") {
return response.data.data;
}
this.setState({
questions: [...response.data.questions.items],
question_id: response.data.questions.items.id
});
});
};
}
export default App;
In the App.js i am passing the method handleSentData to the child component AccordionItem where i map the items and data.id returns the Id
this.state.questions.map((data, index) => (
<AccordionItem key={index} index={data.id} QST={this.handleQuestionId}/>
))
I have this method in the AccordionItem component, everytime i click an item i get the ID of the item and i pass the props.QST(index) to the parent App.js
const eventHandler = (e, index) => {
e.preventDefault();
setActive(index);
props.QST(index)
}
I need to add the state of question_id to newData.params so i can pass it as parameter to the url
Looking at your code, I don't see where you go through and render the question's array. But the most practical approach would be that when you apply map on the array, you obtain the id of the question and pass it to the necessary component, in this case I guess it would be the answer button. And you add that new parameter in the handleSentData function. I am not sure, because I am a bit confused, it is not clear to me if the code you have is working or it is a sketch of what you want to achieve.
I made a little example, maybe it can serve you as a guide:
import React, { useState } from "react";
const questions = [
{ id: 1, text: "What is 2 plus 2?" },
{ id: 2, text: "What is 10 plus 10?" }
];
const answers = [
{ id: 1, text: "It is 4" },
{ id: 2, text: "It is 8" }
];
const fetchAnswer = (questionId) => {
const answer = answers.find((answer) => answer.id === questionId);
return answer ? answer.text : "I don't really know";
};
const Questions = (props) => {
const { questions, handleSentData } = props;
return (
<ul>
{questions.map((question) => {
return (
<li key={question.id}>
<span>{question.text}</span>
<button onClick={() => handleSentData(question.id)}>
Answer this question
</button>
</li>
);
})}
</ul>
);
};
export default function App() {
const [answer, setAnswer] = useState(null);
const handleSentData = (questionId) => {
// Fetch answers from somewhere using the question id.
const response = fetchAnswer(questionId);
console.log(response);
setAnswer(response);
};
return (
<div className="App">
<h1>Questions</h1>
<Questions questions={questions} handleSentData={handleSentData} />
<h1>Answer</h1>
<div>{answer ? answer.text : "Your answer will appear here!"}</div>
</div>
);
}