Создал тест с использованием React, пытаясь создать систему закладок, в которой пользователи могут добавлять вопросы из теста - PullRequest
1 голос
/ 19 февраля 2020

Используя React, я создал тест, в котором пользователи получают вопросы и могут выбирать ответы: https://codesandbox.io/s/quiz-1cf1m

Я пытаюсь добавить функцию закладки, где пользователь может «добавить в закладки» вопросы, к которым он хочет вернуться позже. И после завершения теста можно отобразить список вопросов, которые они добавили в закладки в Сводке результатов (и, надеюсь, нажмите, чтобы перейти к этому конкретному c вопросу).

В своем компоненте вопросов я добавил для isBookMarked значение false и bookmarkedQuestions установлен в пустой массив. Затем создал функцию handleBookmark, которая переключает значок закладки.

class Question extends React.Component {
  state = {
    pick: false,
    correct: false,
    isBookmarked: false,
    bookmarkedQuestions: []
  };

  correctOrIncorrect = pick => {
    if (pick === this.state.pick) {
      return this.state.correct ? "correct" : "incorrect";
    } else if (
      pick === !this.state.correct &&
      this.props.currentQuestion.correctAnswer
    ) {
      return "correct";
    } else {
      return "clear";
    }
  };

  handleSelect = pick => {
    if (pick === this.props.currentQuestion.correctAnswer) {
      this.setState({ pick, correct: true });
    } else {
      this.setState({ pick });
    }
  };

  moveToNextQuestion = () => {
    this.setState({ pick: false, correct: false });
    this.props.nextQuestionHandler(this.state.correct);
  };

  handleBookmark = () => {
    console.log(this.props.currentQuestion);

    this.setState({
      isBookmarked: !this.state.isBookmarked
    });
  };

  render() {
    const { currentQuestion, shuffledAnswerChoices } = this.props;

    return (
      <div className={this.props.animation ? this.props.animation : null}>
        <span>
          <i
            id={currentQuestion}
            className={
              this.state.isBookmarked ? "fa fa-bookmark" : "fa fa-bookmark-o"
            }
            onClick={() => this.handleBookmark()}
          />
        </span>
        <p>{currentQuestion.text}</p>
        <ol type="A">
          {shuffledAnswerChoices.map((pick, idx) => {
            return (
              <li
                key={idx}
                className={this.state.pick ? this.correctOrIncorrect(pick) : null}
                onClick={() => this.handleSelect(pick)}
              >
                {pick}
              </li>
            );
          })}
        </ol>
        {this.state.pick && (
          <div>
            {this.state.correct ? (
              <p>
                <i>Correct!</i>
              </p>
            ) : (
              <p>
                <i>Incorrect</i>
              </p>
            )}
            <button className="next-btn" onClick={this.moveToNextQuestion}>
              Next
            </button>
          </div>
        )}
      </div>
    );
  }
}

export default Question;

Я понял, что с текущим кодом, который у меня есть, когда я добавляю закладку, значок остается добавленным в закладки на протяжении всего теста, пока я не нажму еще раз, чтобы снять его с закладки. Я добавил консольный журнал и могу получить текущий вопрос, на котором я нахожусь. Я застрял в возможности отметить только выбранные вопросы, и как только пользователь переходит к следующему вопросу, он «сбрасывается». Я также пытаюсь поместить sh вопрос в пустой массив bookmarkedQuestions при добавлении в закладки, который я хочу отобразить в конце теста (но только что понял, что Компонент Результата является родным братом, а не дочерним элементом Компонента Вопроса, и следовательно, не может считаться реквизитом ...).

Какие-нибудь React Pros, которые могут научить меня, как подойти к этой проблеме ...?

Дополнительный вопрос, расширяющийся из этой системы закладок : любые подходы к предложению о том, как повторить все неправильные вопросы снова, пока на все вопросы не будут даны правильные ответы с кратким описанием, показывающим, сколько вопросов было дано правильно в первый раз?

1 Ответ

1 голос
/ 19 февраля 2020

Определенно не React Pro, но я думаю, что могу помочь!

По моему мнению, вам следует переместить состояние закладки на уровень Викторины, чтобы оно сохранялось в течение всей викторины. Это означает передачу функции из вопроса в вопросник для контроля состояния вопросов, отмеченных закладкой. Это также означает, что флаг «isBookmarked» также передается как опора.

Это может означать создание логи c, которые слишком усложняют то, что вы хотите сделать.

ДЛИННЫЙ ПРИМЕР (Некоторые части слишком сложны для того, что нужно сделать) - не стесняйтесь не использовать какие-либо об этом, но я вошел в это так, чувствовал, что добавляю это: https://codesandbox.io/s/quiz-x8wpv?fontsize=14&hidenavigation=1&theme=dark

Я возился с вашим кодом и создал пример того, как он будет работать. Структура данных, которую я выбрал для закладок, представляет собой объект с ключом верхнего уровня теста [quizNumber], значение которого представляет собой другой объект, ключами которого являются каждый вопрос. Который затем будет иметь логический флаг, который будет указывать, если в закладки или нет. Для достижения этой цели было бы полезно добавить идентификатор поля для каждого вопроса

Чтобы избежать хранения большого количества данных, я пропустил фактический вопрос из структуры данных, поскольку его можно затем найти с помощью quizNumber и идентификатора вопроса.

Итак, я позволил себе обновить вопросы, чтобы они соответствовали этому стилю

  {
        qID: 1,
        text: "What is the capital of United States?",
        correctAnswer: "Washington, D.C.",
        incorrectAnswers: ["Philadelphia", "Annapolis", "New York City"]
      }

Итак, пример структуры объекта bookmarkkedQuestions:

{
 '0':{1:true},
 '2':{1:false, 2:true , 3:true}
}

Этот пример будет означать, что вопрос 0 для вопроса 1 был добавлен в закладки, а также вопрос 2 и 3 для теста. Если ключ не существует или является ложным, можно предположить, что вопрос не был добавлен в закладки.

Для установки эта функция на уровне викторины должна быть создана. Созданная мною функция, скорее всего, слишком сложна для выполнения необходимых задач, но выглядит следующим образом:

  bookmarkQuestion = () => {
    const { currentQuiz, numOfQuestions, quizQuestionBookmarks } = this.state;
    const { questions } = quizzes[currentQuiz];
    const { qID } = questions[numOfQuestions];
    // Can be simplified by creating a function to update nested values, or by using lodash
    // The destructuring is required so other parts of the object are not modified when updated deeper keys
    this.setState({
      quizQuestionBookmarks: {
        ...quizQuestionBookmarks,
        [currentQuiz]: {
          ...quizQuestionBookmarks[currentQuiz],
          [qID]: quizQuestionBookmarks[currentQuiz]
            ? !quizQuestionBookmarks[currentQuiz][qID]
            : true
        }
      }
    });
  };

Идея состоит в том, что теперь ее можно использовать в currentQuizQuestions для получения списка вопросов, которые в настоящий момент добавлены в закладки. ,

  getBookmarkedQuestions = () => {
    const { currentQuiz, quizQuestionBookmarks } = this.state;
    const { questions } = quizzes[currentQuiz];
    const boorkmarkedQuestions = questions.filter(question =>
      quizQuestionBookmarks[currentQuiz]
        ? quizQuestionBookmarks[currentQuiz][question.qID]
        : false
    );
    return boorkmarkedQuestions;
  };

В моем примере я также передаю закладки с закладками на страницу результатов в качестве опоры, чтобы продемонстрировать, как данные могут быть переданы для использования.

...