这是一个面试项目,赐教还有哪些需要优化的地方? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
mascteen
V2EX    程序员

这是一个面试项目,赐教还有哪些需要优化的地方?

  •  1  
  •   mascteen
    janegwaww 2020 年 12 月 16 日 3492 次点击
    这是一个创建于 1852 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Table of Contents

    1. 这是一个面试项目,赐教还有哪些需要优化的地方?
    2. 项目需求
    3. 我的代码

    这是一个面试项目,赐教还有哪些需要优化的地方?

    这是一个公司的面试小项目,根据数据生成多选框,要有一个全选的选项目,这是我的代码,请问还有哪些需要改进的地方和不足?因为对方不回复,只能来这里求教。

    项目需求

    1. 写一个多选框小组件;
    2. 需要有单元测试
    3. 有全选选项目
    4. 样式符合需求
    5. 用 react,typescript,jest 技术
    6. 全程不能出现中文
    7. 需要有意义的注释
    8. 代码尽量优美
    9. 取名优美
    10. 最后提交 PR 审核

    我的代码

    • 多选框组件 MultiCheck.tsx

       import React, { useState, useEffect, FunctionComponent } from "react"; import { fpMap, pipe } from "../utils"; import "./MultiCheck.css"; export type Option = { label: string; value: string; checked: boolean; }; /** * Notice: * 1. There should be a special `Select All` option with checkbox to control all passing options * 2. If columns > 1, the options should be placed from top to bottom in each column * * @param {string} label - the label text of this component * @param {Option[]} options - options * @param {number} columns - default value is 1 * @param {Function} onChange - when checked options are changed, * they should be passed to outside */ type Props = { label?: string; options: Option[]; columns?: number; onChange?: (options: Option[]) => void; }; const selectAll = (c = false) => ({ label: "Select All", value: "Select All", checked: c }); const MultiCheck: FunctionComponent<Props> = (props): JSX.Element => { const { label = "", columns = 1, OnChange= () => {} } = props; const [value, setValue] = useState({}); // for call props.onChange const [options, setOptions] = useState<Option[]>([ /* if original options all checked */ selectAll(!hasUnchecked(props.options)), ...props.options ]); function hasUnchecked(o: Option[]) { return o.filter(o => o.value !== selectAll().value).some(o => !o.checked); } function _handleClick(o: Option): void { /* user toggle click checkbox */ const cOnvertCheck= fpMap(i => { if (i.value === o.value) { return { ...i, checked: !o.checked }; } return i; }); /* user toggle click SelectAll option */ const cOnvertSelectAll= fpMap(i => { if (selectAll().value === o.value) { return { ...i, checked: !o.checked }; } return i; }); /* if all other option checked than SelectAll option checked else unchecked */ const isAllChecked = (o: Option[]) => { return fpMap(i => { if (i.value === selectAll().value) { return { ...i, checked: !hasUnchecked(o) }; } return i; })(o); }; setOptions(prev => pipe(convertCheck, convertSelectAll, isAllChecked)(prev) ); setValue(o); } function _getColumns(n: number): number { return n > 0 ? Math.ceil(options.length / n) : 1; } useEffect(() => { /* selectAll option can not be pass outside */ onChange(options.filter(i => i.value !== selectAll().value)); }, [value]); return ( <div className="multi-check-container"> <div className="multi-check"> <div className="multi-check-label"> <label>{label}</label> </div> <div className="multi-check-items" style={{ gridTemplateRows: `repeat(${_getColumns(columns)},auto)` }} > {fpMap(o => ( <label className="multi-check-item" key={o.value}> <input type="checkbox" value={o.value} checked={o.checked} OnChange={() => _handleClick(o)} /> <span></span> <div>{o.label}</div> </label> ))(options)} </div> </div> </div> ); }; export default MultiCheck; 
    • 测试用例

       import "@testing-library/jest-dom"; import React from "react"; import renderer from "react-test-renderer"; import { fireEvent, render, screen } from "@testing-library/react"; import { fpMap, pipe } from "../utils"; import MultiCheck from "./MultiCheck"; describe("MultiCheck", () => { describe("initialize", () => { it("renders correctly", () => { const tree = renderer.create(<MultiCheck optiOns={[]} />).toJSON(); expect(tree).toMatchSnapshot(); }); it("renders the label if label provided", () => { const label = "jest test"; render(<MultiCheck optiOns={[]} label={label} />); expect(screen.queryByLabelText(label)).toBeDefined(); }); it("render and click checkbox", () => { const optiOns= [{ label: "test", value: "test", checked: false }]; render(<MultiCheck optiOns={options} />); expect(screen.queryByLabelText(/test/i)).not.toBeChecked(); // simulate user click checkbox fireEvent.click(screen.getByLabelText(/test/i)); expect(screen.queryByLabelText(/test/i)).toBeChecked(); }); }); describe("utils", () => { it("fpMap", () => { let arr = [1, 2, 3]; let add1 = (o: number) => o + 1; expect(fpMap(add1)(arr)).toEqual([2, 3, 4]); }); it("pipe", () => { let arr = [1, 2, 3]; let add1Each = (i: []) => i.map(o => o + 1); let prod2Each = (i: []) => i.map(o => o * 2); expect(pipe(add1Each, prod2Each)(arr)).toEqual([4, 6, 8]); }); }); }); 
    • 工具代码 utils.ts

       type fn = (arg: any) => any; // functional programming for map iterator export function fpMap(func: fn): fn { return function(arr: unknown[]): unknown[] { let length: number = arr.length || 0; let i: number = 0; let result: unknown[] = []; while (i < length) { result.push(func(arr[i])); i++; } return result; }; } // functional programming pipe export function pipe(...fns: fn[]): fn { return function(x: any) { return fns.reduce((v: any, f: fn) => f(v), x); }; } 
    12 条回复    2020-12-16 19:09:59 +08:00
    mascteen data-uid=
        1
    mascteen  
    OP
       2020 年 12 月 16 日
    很完美么?
    tesguest123
        2
    tesguest123  
       2020 年 12 月 16 日 via iPhone
    交完后,你不适合我们公司 doge 。白嫖一波
    mascteen
        3
    mascteen  
    OP
       2020 年 12 月 16 日 via Android
    @tesguest123 对呀,所以来这里问问
    aaronlam
        4
    aaronlam  
       2020 年 12 月 16 日
    这是个现场上机题?
    Chrisssss
        5
    Chrisssss  
       2020 年 12 月 16 日
    比如 `_getColumns` 不关乎业务的东西可以提到 FC 外面去,部分 any 定义使用泛型,有一些代码风格不太好,比如 `selectAll` 函数的 c 参数命名,其实可以用 `checked`,然后里面直接`{
    label: "Select All",
    value: "Select All",
    checked
    }` 就好。`‘Select All’` 可以定义一个常量。这些就是我作为面试官的话看了一眼会给你扣分的地方
    Chrisssss
        6
    Chrisssss  
       2020 年 12 月 16 日
    其实还有很多问题
    buhi
        7
    buhi  
       2020 年 12 月 16 日
    好好的 Array#map 不用, 造了个 any=>any=>(any[])=>any[], 一通下来全给你整 any 了
    这就是你认为的函数式编程吗? 遇见我同事这么做直接打死了
    mascteen
        8
    mascteen  
    OP
       2020 年 12 月 16 日 via Android
    @aaronlam 不是,github
    mascteen
        9
    mascteen  
    OP
       2020 年 12 月 16 日 via Android
    @buhi 大哥这能一样么?
    mascteen
        10
    mascteen  
    OP
       2020 年 12 月 16 日 via Android
    @Chrisssss 没时间打字?
    mascteen
        11
    mascteen  
    OP
       2020 年 12 月 16 日 via Android
    @Chrisssss 是有一些不足,不过这是一道面试题,我不会花太多时间在上面的
    yzbythesea
        12
    yzbythesea  
       2020 年 12 月 16 日
    逻辑挺简单的,但是我就是读不懂你的代码。。。

    为什么不用 array 存 option ?单独造一个 selectAll 的类干什么?为什么不把 selectAll 当作一个 option 加进去呢?

    然后 checkbox 的逻辑都可以但写出 function,再套进里面,你这么写看着好晕。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2634 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 04:05 PVG 12:05 LAX 20:05 JFK 23:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86