React多步骤表单如何将选中卡片的分类数据传递到下一步渲染对应内容
实现方案
1. 改造第一步分类选择组件,存储选中分类到全局Context
你已经配置了全局的QuizContext用来跨组件传值,只需要在点击下一步的时候把选中的分类存入Context即可,修改后的TacoCathegories代码如下:
import { Card } from "../../stories/Card"; import { useQuizData } from "../../context/index" import { useState } from "react"; const tacos = [ { cathegory: 'Meat', imgURL: 'https://images.unsplash.com/photo-1560781290-7dc94c0f8f4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3024&q=80' }, { cathegory: 'Fish', imgURL: 'https://images.unsplash.com/photo-1510130387422-82bed34b37e9?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=975&q=80' }, { cathegory: 'Veggi', imgURL: 'https://images.unsplash.com/photo-1572527129705-a6c197003d61?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=975&q=80' }, ] export const TacoCathegories = ({quizStep, prevQuizStep, nextQuizStep}) => { // 取消注释,拿到Context的存值方法 const { setQuizValues } = useQuizData(); const [isSelected, setisSelected] = useState(); return ( <div className={quizStep === 0 ? 'block': 'hidden'}> <div className="text-center"> <h2 className="text-3xl font-extrabold tracking-tight text-gray-600 sm:text-4xl">What is your favourite taco group?</h2> </div> <div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8"> <div className="mt space-y-12 lg:space-y-0 lg:grid lg:grid-cols-3 lg:gap-x-8"> {tacos.map((taco, index) => ( <Card role="button" key={index} title={taco.cathegory} source={taco.imgURL} text={`image of ${taco.cathegory} `} selected={isSelected === index} onChange={() => setisSelected(index)} /> ))} </div> {tacos[isSelected] && <p>{tacos[isSelected].cathegory}</p>} <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-center"> <div className="rounded-md shadow"> <a role="button" tabIndex={0} className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-gray-200 hover:bg-gray-200 focus:outline-none md:py-4 md:text-lg md:px-10 cursor-not-allowed" > Back </a> </div> <div className="mt-3 sm:mt-0 sm:ml-3"> <a onClick={() => { // 先判断是否选中分类 if (tacos[isSelected]) { // 把选中的分类存入全局Context setQuizValues({ selectedCategory: tacos[isSelected].cathegory }) // 再跳转到下一步 nextQuizStep() } }} // 未选中时禁用下一步按钮,优化体验 className={`w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white md:py-4 md:text-lg md:px-10 ${isSelected !== undefined ? 'bg-yellow-500 hover:bg-yellow-600' : 'bg-gray-200 cursor-not-allowed'}`} > Next </a> </div> </div> </div> </div> ); }
核心改动点:
- 取消了
useQuizData引入的注释,拿到全局存值方法setQuizValues - 修改下一步按钮的点击逻辑,先将选中的分类存入Context再跳转
- 新增未选中分类时禁用下一步的逻辑,优化交互体验
2. 改造第二步组件,从Context读取分类渲染对应内容
直接在第二步组件中调用useQuizData拿到全局存储的选中分类,根据分类值渲染对应的塔可列表即可,修改后的TacoTypes代码如下:
import { useQuizData } from "../../context/index" // 可以根据需求配置不同分类对应的塔可列表,这里举个示例 const TACO_TYPE_CONFIG = { Meat: [ { name: '牛肉塔可', img: 'xxx' }, { name: '猪肉塔可', img: 'xxx' }, { name: '鸡肉塔可', img: 'xxx' }, ], Fish: [ { name: '三文鱼塔可', img: 'xxx' }, { name: '鳕鱼塔可', img: 'xxx' }, { name: '鲜虾塔可', img: 'xxx' }, ], Veggi: [ { name: '牛油果塔可', img: 'xxx' }, { name: '蔬菜塔可', img: 'xxx' }, { name: '菌菇塔可', img: 'xxx' }, ] } export const TacoTypes = ({quizStep, prevQuizStep, nextQuizStep}) => { // 从全局Context拿到选中的分类 const { data } = useQuizData(); const selectedCategory = data.selectedCategory; // 根据分类拿到对应的塔可列表 const showTacos = TACO_TYPE_CONFIG[selectedCategory] || []; return ( <div className={quizStep === 1 ? 'block' : 'hidden'}> <div> <p>你选择的分类是:{selectedCategory}</p> <p>对应的塔可类型如下:</p> <div className="grid grid-cols-3 gap-4 mt-4"> {showTacos.map((taco, idx) => ( <div key={idx} className="border p-2 rounded"> {taco.name} {/* 可以替换成Card组件渲染,和第一步逻辑一致 */} </div> ))} </div> </div> <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-center"> <div className="rounded-md shadow"> <a role="button" tabIndex={0} onClick={prevQuizStep} className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-yellow-500 hover:bg-yellow-600 md:py-4 md:text-lg md:px-10" > Back </a> </div> <div className="mt-3 sm:mt-0 sm:ml-3"> <a onClick={nextQuizStep} className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-yellow-500 hover:bg-yellow-600 md:py-4 md:text-lg md:px-10" > Next </a> </div> </div> </div> ) }
额外小提示:你代码里的yallow是拼写错误,正确应为yellow,可以顺便修正避免样式不生效。
内容的提问来源于stack exchange,提问作者Katharina Schreiber
相关产品推荐
相关产品推荐

