使用 refs 和 .reduce 滚动到所选元素的 id 并与 useState 反应

Using refs and .reduce scroll to the id of selected element with react with useState

抱歉,如果标题没有多大意义。

我一直在将我的代码从 this.state 重构为 useState,我终于让除了 refs 之外的东西正常工作...

在我的原始代码中,我进行了单独的 axios 调用并使用 this.state 以及此参考代码:

const refs = response.data.reduce((acc, value) => {
acc[value.id] = createRef();
return acc;
}, {});

但现在我重构了对 .all 的 axios 调用:

const getData = () => {
    const getSunSigns = axios.get(sunSignAPI);
    const getDecans = axios.get(decanAPI);
    const getNums = axios.get(numbersAPI);

    axios.all([getSunSigns, getDecans, getNums, refs]).then(
      axios.spread((...allData) => {
        const allSunSigns = allData[0].data;
        const getAllDecans = allData[1].data;
        const getAllNums = allData[2].data;

        setSunSigns(allSunSigns);
        setDecanSign(getAllDecans);
        setNumerology(getAllNums);
      })
    );
  };

  useEffect(() => {
    getData();
  }, []);

所以 response.data.reduce 不起作用,因为我没有使用 'response'。

我尝试了几件事,但 none 奏效了。不幸的是,我删除了所有以前的代码,但这是我目前拥有的代码,它可以工作,但显然只需要一个 api:

const refs = sunSigns.reduce((acc, value) => {
    acc[value.id] = createRef();
    return acc;
  }, {});

  onClick = (id) => {
    refs[id].current.scrollIntoView({
      behavior: "smooth",
    });
  };

根据我所做的研究和我尝试过的代码,我确定我必须通过 api 进行映射,然后可能使用 reduce(???)..但我真的不完全确定如何着手或如何重新措辞我的 google 搜索以获得更准确的结果。

我正在尝试做的具体事情:在某些页面上会出现一个带有特定 sign/number 符号的额外导航栏。用户可以点击其中一个,它会滚动到那个特定的。我将有几个页面具有这种功能,因此我需要为每个 api.

动态设置 refs

任何帮助或指导将不胜感激!!

编辑**

以上代码在我的主要组件中,这是我设置引用的地方:

  return (
    <div className='main'>
      <div className='main__side-container'>
        <SideBar />
        <div className='main__card-container'>
          <Card
            sunSigns={sunSigns}
            numerology={numerology}
            decanSign={decanSign}
            refs={refs}
          />
        </div>
      </div>
      <div className='main__bottom-container'>
        <BottomBar
          sunSigns={sunSigns}
          numerology={numerology}
          onClick={onClick}
        />
      </div>
    </div>
  );
}

那么这是卡片:

export default function Card({ sunSigns, decanSign, refs, numerology }) {
    return (
        <>
          <div className='card'>
            <Switch>
              <Route path='/astrology/western/zodiac'
                render={(routerProps) => <Zodiac refs={refs} sunSigns={sunSigns} />}
              />
              <Route path='/numerology/pythagorean/numbers'
                render={(routerProps) => <NumberPage refs={refs} numerology={numerology} />}
              />
            </Switch>
          </div>
        </>
      );
    }

然后这是生肖页面:

export default function Zodiac({ sunSigns, refs }) {
  return (
    <>
      <div className='zodiac__container'>
        <TitleBar text='ZODIAC :' />
        <div className='card-inset'>
        <div className='container-scroll'>
          <SunSignsList sunSigns={sunSigns} refs={refs} />
        </div>
        </div>
        
      </div>
    </>
  );
}

和 SunSignsList 组件:

export default function SunSignsList({ sunSigns, refs }) {
  return (
    <>
      <div className='sunsignsitemlist'>
        <ul>
          {sunSigns.map(sign => {
            return (
              <SunSigns
                refs={refs}
                key={sign.id}
                id={sign.id}
                sign={sign.sign}
                />
                );
              })}
        </ul>
      </div>
    </>
  );
} 

和 SunSigns 组件:

export default function SunSigns({
  id,
  sign,
  decans,
  refs
}) {
  return (
    <li ref={refs[id]}>
      <section className='sunsigns'>
        <div className='sunsigns__container'>
          <div className='sunsigns__header'>
            <h3 className='sunsigns__title'>
              {sign}
              {decans}
            </h3>
            <h4 className='sunsigns__symbol'>{symbol}</h4>
      </section>
    </li>
  );
}

以上代码是我的参考代码当前正确访问的地方。但最终目标是以相同的方式在多个页面和组合中使用它们。

您可以创建三个不同的对象来保存每个列表的引用数据,或者如果 id 相同,您可以生成一个包含所有列表引用的对象。

const generateAllRefsObj = (...args) => {
  const genSingleListRefsObj = (acc, value) => {
    acc[value.id] = createRef();
    return acc;
  }
  return args.reduce((acc, arg) => ({ ...arg.reduce(genSingleListRefsObj, acc), ...acc }), {})
}

用法

const allRefs = generateAllRefsObj(sunSigns,decanSign,numerology)