kanfutrooper
@kanfutrooper (masaomi)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Basics.js、Questionnaire.js、Optional.jsで答えた回答をConfirm.jsで表示したい

Q&A

Closed

ReactでMaterial-UI を使用して、Web フォームを作成しています。

Basics.js、Questionnaire.js、Optional.jsの質問は、Confirm.js表示されるのだが、答えた回答は表示できていないので、 Basics.js、Questionnaire.js、Optional.jsの質問及び答えた回答をConfirm.jsで表示したいです。

どのように実装したら良いかわからない状況で、詰まっています。 何方かアドバイスをお願いします。

期待する動作

Basics.js、Questionnaire.js、Optional.jsの質問及び答えた回答をConfirm.jsで表示したいです。

問題解決のため行なったこと

Basics.js、Questionnaire.js、Optional.jsをConfirm.jsで表示したかったので、それは何とか実装できたが、
質問及び答えた回答の実装の仕方がわからない。

App.js
import { Grid } from "@mui/material";
import Header from "./components/Header";
import Content from "./components/Content";

function App() {
  return (
    <Grid container direction="column">
      <Header />
      <div style={{ padding: 30 }}>
        <Content />
      </div>
    </Grid>
  );
}
export default App;
src / components / contents.js
contents.js
import React from "react";
import { Grid } from "@mui/material";
import Stepper from "@mui/material/Stepper";
import Step from "@mui/material/Step";
import StepLabel from "@mui/material/StepLabel";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Basic from "./Basic";
import Questionnaire, { QUESTIONS } from "./Questionnaire";
import Optional from "./Optional";
import Confirm from "./Confirm";

unction getSteps() {
  return ["お客様の情報を入力して下さい", "以下にお答え下さい", "ご相談下さい", "以下の内容をご確認下さい"];
}
const StepContent = ({ stepIndex, questionnaireProps }) => {
  switch (stepIndex) {
    case 0:
      return <Basic />;
case 1:
      return <Questionnaire {...questionnaireProps} />;
    case 2:
      return <Optional />;
case 3:
      return <Confirm />;
    default:
      return "Unknown stepIndex";
  }
};
function Content() {
  const [activeStep, setActiveStep] = React.useState(0);
  const [answers, setAnswers] = React.useState(Array(QUESTIONS.length).fill(null));
  const steps = getSteps();
  const handleNext = () => {
    setActiveStep((prevActiveStep) => prevActiveStep + 1);
  };
const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };
  const handleReset = () => {
    setActiveStep(0);
  };
  const buttonDisabled = activeStep === 1 && answers.some((a) => !a);
  return (
    <Grid container>
      <Grid sm={2} />
      <Grid lg={8} sm={8} spacing={10}>
        <Stepper activeStep={activeStep} alternativeLabel>
          {steps.map((label) => (
            <Step key={label}>
              <StepLabel>{label}</StepLabel>
            </Step>
          ))}
        </Stepper>
        {activeStep === steps.length ? (
          <div>
            <Typography>全ステップの表示を完了</Typography>
            <Button onClick={handleReset}>リセット</Button>
          </div>
        ) : (
          <div>
            <Typography>
              <StepContent stepIndex={activeStep} questionnaireProps={{ answers, setAnswers }} />
            </Typography>
            <Button disabled={activeStep === 0} onClick={handleBack}>
              戻る
            </Button>
            <Button variant="contained" color="primary" onClick={handleNext} disabled={buttonDisabled}>
              {activeStep === steps.length - 1 ? "送信" : "次へ"}
            </Button>
          </div>
        )}
      </Grid>
    </Grid>
  );
}
export default Content;
src / components / Basics.js
Basics.js
import React from "react";
import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import FormControl from "@mui/material/FormControl";
import FormLabel from "@mui/material/FormLabel";
import InputLabel from "@mui/material/InputLabel";
import Select from "@mui/material/Select";

const Basic = () => {
  return (
    <>
      <div style={{ textAlign: "center" }}>
        <FormControl component="fieldset">
          <FormLabel component="legend">- 性別 -</FormLabel>
          <RadioGroup row aria-label="gender" name="row-radio-buttons-group">
            <FormControlLabel value="male" control={<Radio />} label="男性" />
            <FormControlLabel value="female" control={<Radio />} label="女性" />
          </RadioGroup>
        </FormControl>
      </div>
      <div style={{ textAlign: "center" }}>
        <FormLabel component="legend">- 生年月日 -</FormLabel>
        <FormControl sx={{ m: 1, minWidth: 120 }}>
          <InputLabel htmlFor="grouped-native-select">year</InputLabel>
          <Select native defaultValue="" id="grouped-native-select" label="Grouping">
            <option aria-label="None" value="" />
            <optgroup label="year">
              {Array.from(Array(2020), (_, num) => (
                <option key={num} value={num + 1}>
                  {num + 1990}
                </option>
              ))}
            </optgroup>
          </Select>
        </FormControl>
        <FormControl sx={{ m: 1, minWidth: 120 }}>
          <InputLabel htmlFor="grouped-native-select">month</InputLabel>
          <Select native defaultValue="" id="grouped-native-select" label="Grouping">
            <option aria-label="None" value="" />
            <optgroup label="month">
              {Array.from(Array(12), (_, num) => (
                <option key={num} value={num + 1}>
                  {num + 1}
                </option>
              ))}
            </optgroup>
          </Select>
        </FormControl>
        <FormControl sx={{ m: 1, minWidth: 120 }}>
          <InputLabel htmlFor="grouped-native-select">day</InputLabel>
          <Select native defaultValue="" id="grouped-native-select" label="Grouping">
            <option aria-label="None" value="" />
            <optgroup label="day">
              {Array.from(Array(12), (_, num) => (
                <option key={num} value={num + 1}>
                  {num + 1}
                </option>
              ))}
            </optgroup>
          </Select>
        </FormControl>
      </div>
    </>
  );
};
export default Basic;
src / components / Questionnaire.js
Questionnaire.js
import FormControlLabel from "@mui/material/FormControlLabel";
import FormControl from "@mui/material/FormControl";
import FormLabel from "@mui/material/FormLabel";

export const QUESTIONS = [
  "現在、生命保険に加入されていますか?",
  "現在、入院中ですか。また、3ヶ月以内に医師の診察・検査の結果、入院・手術をすすめられたことがありますか?",
  "過去、5年以内に病気やケガで手術を受けたことまたは継続して7日以上の入院をしたことはありますか?",
];

const Questionnaire = ({ answers, setAnswers }) => {
  const handleAnswer = (answeredIndex, answer) => {
    setAnswers(answers.map((e, i) => (i === answeredIndex ? answer : e)));
  };
  return (
    <div>
      <FormControl component="fieldset">
        {answers
          .filter((_, i) => i === 0 || answers[i - 1])
          .map((answer, i) => (
            <React.Fragment key={i}>
              <FormLabel component="legend">{QUESTIONS[i]}</FormLabel>
              {answer ? (
                <Typography>{answer === "yes" ? "はい" : "いいえ"}</Typography>
              ) : (
                <RadioGroup
                  row
                  aria-label="gender"
                  name="row-radio-buttons-group"
                  onChange={(_evt, value) => {
                    handleAnswer(i, value);
                  }}
                >
                  <FormControlLabel value="yes" control={<Radio />} label="はい" />
                  <FormControlLabel value="no" control={<Radio />} label="いいえ" />
                </RadioGroup>
              )}
            </React.Fragment>
          ))}
      </FormControl>
    </div>
  );
};

export default Questionnaire;


src / components / Optional.js
Optional.js
import React from "react";
import { Grid } from "@mui/material";
import Tooltip from "@mui/material/Tooltip";
import TextField from "@mui/material/TextField";

const Optional = () => {
  return (
    <div>
      <Grid container>
        <Grid sm={2} />
        <Grid lg={8} sm={8} spacing={10}>
          <Tooltip title="ご相談内容を記入することができます" placement="top-start" arrow>
            <TextField
              label="ご相談内容"
              fullWidth
              margin="normal"
              rows={4}
              multiline
              variant="outlined"
              placeholder="その他ご要望等あれば、ご記入ください"
            />
          </Tooltip>
        </Grid>
      </Grid>
    </div>
  );
};
export default Optional;


src / components / Confirm.js
Confirm.js
import React from "react";
import Basic from "./Basic";
import Questionnaire, { QUESTIONS } from "./Questionnaire";
import Optional from "./Optional";

export const UserInputData = React.createContext();

function Confirm() {
  const [currentState, setCurrentState] = React.useState({});
  const [answers, setAnswers] = React.useState(Array(QUESTIONS.length).fill(null));

  const value = {
    currentState,
    setCurrentState,
  };
  return (
    <div style={{ textAlign: "center" }}>
      <Basic />
      <Questionnaire answers={answers} setAnswers={setAnswers} />
      <Optional />
    </div>
  );
}

export default Confirm;
0

2Answer

const [answers, setAnswers] = React.useState(...)
  1. 上記のようなコードがcontentとconfirmと両方同じようにありますが、contentだけにあったら良いのでは?
  2. <Questionnaire/>がありますが、ソースは掲載されていないのでよくわからない。
  3. にはpropsが渡されていないし、formの内容を何らかの方法で保存している様子もない。

もの凄いシンプルにしてcodesandboxに動くものを作れますか?

0Like

Comments

  1. @kanfutrooper

    Questioner

    @github0013@githubさん、丁寧な回答及び解説、ありがとうございます!
    『<Questionnaire/>がありますが、ソースは掲載されていないのでよくわからない。』というご指摘なんですが、元の質問に編集し直しました。お手数かけて、申し訳ございません。
  2. そもそもsetAnswersをpropsとして渡しているという点は置いておいて、Basics.jsの方でQuestionnaire.jsでやってるように`setAnswers`をしていない理由はなんですか?
  3. @kanfutrooper

    Questioner

    @github0013@githubさん、回答、ありがとうございます!
    理由は特にないです。
    参考サイトを色々たくさん見て、質問したりして、ここまで仕上げました。
    あと、githubではなく、codesandboxの方が良いですか?

よく分からない時はまずは問題をとにかくシンプルにしてみて理解することが近道だと思います。
作ったcodesandboxは現状のままで、今の状態が難しいのであればまずはシンプルにしてみることです。

  • ステップ数を1,2だけにする(入力 → 表示)
  • 入力項目を1つだけにする(<TextField ... />だけとか)

その上で、まずどうやって入力後から表示ステップにデータが持っていけるのかを考えたほうが理解が早いはずです。
時間があればこちらもcodesandbox上で作ってみますが、まずは自分でやってみることが一番の勉強法だと思います。

0Like

Comments

  1. @kanfutrooper

    Questioner

    @github0013@githubさん、丁寧な回答及び解説、ありがとうございます!
    問題をシンプルにと思って、まず確認画面に基本情報やアンケートを表示するまで実装してみました。その次に基本情報の答えを表示できればと思い、完全に詰まってしまいました。
  2. @kanfutrooper

    Questioner

    @github0013@githubさん、
    Questionnaire.jsの質問の回答はContent.js/case3の確認画面で表示できました!

Your answer might help someone💌