为什么我必须单击两次TextField才能显示列表?

时间:2020-07-20 23:54:53

标签: reactjs material-ui

我从@ material-ui / core @ v4.9.1更新为@ material-ui / core @ v4.11.0。这样做以来,必须单击两次我的所有TextField才能显示列表。该问题似乎与版本更新无关,因为如果切换回v4.9.1版本,问题仍然存在。

package.json

"dependencies": {
    "@material-ui/core": "4.10.2",
    "@material-ui/icons": "^4.9.1",
    "@material-ui/styles": "^4.4.1",

.js文件

    let getBoards = () => {
    const client = new GraphQLClient(url, {
      headers: {
        Authorization: token,
      },
    })

    const query = `{
        boards() {
            id
            name
            owner {
                id
                name
            }
        }
    }`

    client.request(query)
      .then(data => {
        console.log('data: ', data)
        let tempArray = [];

        for (let i = 0; i < data.boards.length; i++) {
          if (data.boards[i].name.indexOf('INT') > -1) {
            tempArray.push({
              id: data.boards[i].id,
              name: data.boards[i].name
            })
          }
        }

        let compare = (a, b) => {
          // Use toUpperCase() to ignore character casing
          const nameA = a.name.toUpperCase();
          const nameB = b.name.toUpperCase();

          let comparison = 0;
          if (nameA > nameB) {
            comparison = 1;
          } else if (nameA < nameB) {
            comparison = -1;
          }
          return comparison;
        }

        setBoards(tempArray.sort(compare));
      })
  }

    <TextField
      required
      error={state.typeErrorBoard}
      select
      label="Select board"
      className={props.classes.textField}
      variant="filled"
      value={state.BoardName}
      onClick={getBoards}
      onChange={e => handleBoardChange(e)}
      margin="dense"
    >
      {boards.map((board, index) =>
        <MenuItem
          key={index}
          value={board.name}
        >
          {board.name}
        </MenuItem>
      )}
    </TextField>

1 个答案:

答案 0 :(得分:1)

提供select prop for the Textfield时,基本上是在渲染select而不是文本字段。

请参见source code

...
   {select ? (
        <Select
          aria-describedby={helperTextId}
          id={id}
          labelId={inputLabelId}
          value={value}
          input={InputElement}
          {...SelectProps}
        >
          {children}
        </Select>
      ) : (
        InputElement
      )}
...
  • 通过上述操作,Textfield的onClick(getBoards)绑定到选择的根div(而不是Textfield)。当您关注Textfield时,将呈现选择的根div。检查元素并看一下。
  • 因此,当您第一次单击Textfield时,select仅呈现(占据整个屏幕),因此不会执行getBoards
  • 但是,当您第二次单击输入时(或在屏幕上的任何位置),将调用getBoards函数,因为select现在位于dom中,onClick处理程序(getBoards)也是如此。
  • 您可以通过在e.target函数中打印e.currentTarget(最初附加事件的位置)和getBoards(触发事件的位置)进行检查

要使其一次单击即可工作,您可以执行以下任一操作:

  • 使用useEffect并调用getBoards
  • 使用onFocus代替onClick

See demo

代码段

export default function MultilineTextFields(props) {
  const classes = useStyles();
  const [boards, setBoards] = React.useState([]);

  let getBoards = e => {
    console.log("e", e.target);
    console.log("e cur", e.currentTarget);
    e.stopPropagation();
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(res => res.json())
      .then(res => {
        console.log("boards", res);
        setBoards(res);
      });
  };

  // useEffect(() => getBoards(), []);  //<----another solution

  return (
    // <div onClick={getBoards}> //<----another solution (don't click on text-input , click on the padding)
    <div>
      <TextField
        required
        // error={state.typeErrorBoard}
        select
        label="Select board"
        className={classes.root}
        variant="filled"
        value={""}
        onClick={getBoards}
        // onFocus={getBoards}  //<----another solution
        // onChange={e => handleBoardChange(e)}
        margin="dense"
      >
        {boards &&
          boards.map((board, index) => (
            <MenuItem key={index} value={board.username}>
              {board.username}
            </MenuItem>
          ))}
      </TextField>
    </div>
  );
}