1

使用数组模拟面包屑

const str = '1/2/3/4/1.text';
const items = str.split('/').reduce((acc, curr) => {
  if (!acc.length) {
    return [curr];
  } else {
    return [...acc, `${acc[acc.length - 1]}/${curr}`];
  }
}, []);
console.log(items)
// ['1', '1/2', '1/2/3', '1/2/3/4', '1/2/3/4/1.text']

useEffect为什么不能直接写async,而useCallback可以?

这是由于useEffect在设计上决定的。
useEffect接受一个函数,这个函数返回undefined或者一个函数(用于cleanup)。

而如果是传给useEffect一个async,那么他将得到一个promise,这与useEffect的预期不符。useCallback就没有cleanup的需要,所以可以自由的使用async

对create-react-app项目使用addLessLoader添加less支持时的报错问题

尝试方案1

  adjustStyleLoaders(({ use: [, , postcss] }) => {
    const postcssOptions = postcss.options;
    postcss.options = { postcssOptions };
  }),

结果:无效

尝试方案2
PostCSS Loader has been initialized using an options object that does not match the API schema

const { override } = require('customize-cra');
const addLessLoader = require('customize-cra-less-loader');

module.exports = override(addLessLoader());

结果:有效

react组件传递参数的方式不同导致的bug

const timestamp = Date.now();

// 只传key
<Demo timestamp />
// Demo组件的props为
// { timestamp: true }

// 传key和value
<Demo timestamp={timestamp} />
// Demo组件的props为
// { timestamp: 1707971983365 }

上面的两种传值方式,会导致得到不同的值,当你明确的知道是需要的是boolean值,并且为true,你当然可以只传key,但有时我们可能意外的将非boolean值使用这种方式传递给组件,因此而导致bug,所以为了避免预料之外的情况,建议始终传递keyvalue

ps: 如果期望的是booleanfalse,那么必须使用keyvalue的形式

<Demo value />
// Demo组件的props为
// { value: true }

<Demo value={false} />
// Demo组件的props为
// { value: false }

react-router-dom@5中的exact作用

用于是否启用精确匹配

当前url/one
exact: false,未开启精确匹配,由于前四位字符一致,所以会匹配/one/two
exact:true,启用精确匹配,由于/one后面的字符不一致,所以不会匹配/one/two
image.png

如何在react@18中使用contenxt?

  1. 创建一个context

    const ThemeContext = React.createContext(null);
  2. 使用ThemeContext.Provider将应用包起来,并且将需要共享的数据传给给value字段。

    <ThemeContext.Provider value="light">
     <App />
    </ThemeContext.Provider>
  3. 使用useContext读取被共享的数据

    function Demo() {
     const theme = useContext(ThemeContext)
    
     return <div>theme: {theme}</div>
    }
  4. 修改context的当前值
    需要借助useState,将setContext作为数据传递给所有组件,这样就可以在任何地方修改顶层的context,并且将更新同步给所有组件了。

    const [context, setContext] = useState(initialState)
    
    <ThemeContext.Provider value={{
     context,
     setContext,
    }}>
     <App />
    </ThemeContext.Provider>

注意事项

createContext的参数是默认值,但是需要注意,这里指的并不是Providervalue不传时,启用createContext的参数作为默认值。而是当组件树上没用使用Provider包裹时,才启用这里的参数作为默认值。

const ThemeContext = React.createContext(null);

如何高亮当前路由?

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

const { pathname } = useLocation();

使用useLocation得到当前pathname,然后使用pathname去与菜单对比,实现当前路由高亮

classnames的动态class如何书写?

const classes = classnames([
  styles.item,
  {
    [styles.active]: true,
  },
]);

当一个useEffect中的函数被外部需要,怎么做?

如下代码,其中loadData在组件初始化的时候需要用到,这很常见,所以我们把它写在了一个空依赖的useEffect中了。

  useEffect(() => {
    const loadData = async () => {
      const res = await getData();
      setItems(res.data);
    };

    loadData();
  }, []);

下面,出现了一个新的需求,我们需要在新增数据后,重新拉取一下远程数据,以保持同步。所以,就需要再次调用loadData,可现在的情况是,loadData被限制在了useEffect中了,该如何解决呢?

使用useCallback

const loadData = useCallback(async () => {
  const res = await getData();
  setItems(res.data);
}, [])

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

const onAdd = () => {
    // ...
    loadData();
}

这样,就可以在外部调用loadData

ps: 如果是删除,那么在确定删除成功后,直接从前端数据中删掉这条数据,也能和远程保持同步。


热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。