2

index.js

App.js

questionData.js

App.js in browser

all I am trying to do where to put generateQuestion function and if I put it in App.js how to pass props form App.js to Quiz.js

please if you have a better implementation of routing & generateQuestion function feel free to leave your recommendations

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Ahmed_Saied
  • 59
  • 1
  • 7

2 Answers2

2

The generateQuestion callback is asynchronous, so you won't be able to send data in route state via the Link, but what you can do is move the onClick handler to the Link and call event.preventDefault on the click event to prevent the navigation action, and issue an imperative navigation after the questions have been fetched.

Example:

import { Link, useNavigate } = 'react-router-dom';

...

const navigate = useNavigate();

...

generateQuestions = async (event) => {
  event.preventDefault();

  try {
    const data = await questionsData();
    const arrData = data.map(element => ({
      ...element,
      id: nanoid(),
    }));

    navigate("/quiz", { state: { questions: arrData } });
  } catch(error) {
    // handle rejected Promise/error/etc...
  }
}

...

<Link to="/quiz" onClick={generateQuestions}>
  <button type="button">
    Start Quiz
  </button>
</Link>
...

In the Quiz component use the useLocation hook to access the passed route state.

import { useLocation } from 'react-router-dom';

...

const { state } = useLocation();
const { questions } = state || {};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
1

For future questions I recommend that you actually write the code instead of pasting a picture so that it's easier to try and answer you.

That aside, I had a similar situation, what I did was the following (Keep in mind that item.document is the property of the data that you want to pass through)

Where you are getting the data in my case I created a new class:

const GetData: React.FunctionComponent<{}> = () => { 
const [information, setInformation] = useState([]);

useEffect(() => {
.
.
//all the request stuff for getting the data
.
.
}

return (
    <div>
        {information.map((item) => (
            <div key={item.id}>
                <Link to="/yourUrl" state={{from:'test', 
                body:`${item.document}`}}> 
                    <div>
                        <h3 >{item.name}</h3>
                        <p>{item.description}</p>
                    </div>
                </Link>
            </div>
        ))}
    </div>
);
}

Remember that .map is in case you want to dynamically creat components depending on the data that you're getting.

Where you want to see and use the data passed:

const Impementation: React.FunctionComponent = () => {
const location = useLocation()
const [itemData, setItemData] = React.useState({
   body: '',
})
.
.
.
useEffect(() => {
   .
   .
   .
   if (location.state) {
     let _state = location.state as any
     setItemData(_state)
   }, [itemData]);
   .
   .
   .
 };

What you did was set the state with the data that came through and then you can use it as you would use states.

This video helped me a lot https://www.youtube.com/watch?v=HLwR7fTB_NM&t=689s