为什么useState钩子不保存变量的值?

时间:2019-08-05 16:10:12

标签: javascript reactjs react-redux material-ui react-hooks

我有一个带有模式的简单表单,该模式用于使用文本框中键入的值来更新我的redux存储。

我正在尝试使用useState挂钩来设置更改时文本框的值。当打印到控制台时,我可以看到我的变量“ note”的值是正确的值。但是,当尝试提交“注释”并将其传递到我的updateCheckpoint函数时,该值是不确定的。

此外,在打开对话框并再次提交时,注释具有正确的值。

function CompetencyCheckpoint(props)
{
    const dispatch = useDispatch();
    let [note, setNote] = useState();

    function updateCheckpoint(note){
        if(note != null){
            console.log("Here is our note : " + note);
        }else{
            console.log("oh no, we didn't get the note");
        }
    }
    console.log(note);
    return (
        <div className="checkpoint-container">
            <i className="material-icons" onClick={()=> 
                dispatch(openDialog({
                children: (
                    <React.Fragment>
                        <DialogTitle id="form-dialog-title">Add Note</DialogTitle>
                        <DialogContent>
                        <DialogContentText>
                            Enter a note.
                        </DialogContentText>
                        <TextField
                            id="filled-textarea"
                            label="New Note"
                            placeholder="Enter note here"
                            multiline
                            value={note}
                            onChange={(e) => setNote(e.target.value)}
                            margin="normal"
                            variant="filled"
                            fullWidth
                        />
                        </DialogContent>
                        <DialogActions>
                        <Button onClick={()=> dispatch(closeDialog())} color="primary">
                            Cancel
                        </Button>
                        <Button onClick={() => updateCheckpoint(note)} color="primary">
                            Add
                        </Button>
                        </DialogActions>
                    </React.Fragment>
                    )
                }))}>
                note_add
            </i>
        </div>);
}

export default (CompetencyCheckpoint);

2 个答案:

答案 0 :(得分:2)

问题在于,对话框内容的JSX在打开对话框时被捕获,并且由于更改note状态而发生重新渲染,因此不会更新。这就是@AhmadNoor的解决方案会导致更多问题的原因-它将您的TextField从不受控制的状态更改为受控制的,但从未收到更新的note值。

您的openDialog函数应仅控制对话框上的open属性。 CompetencyCheckpoint应该更改为直接包含整个Dialog的JSX,而不是作为openDialog调度的参数,因此由于note状态的更改,它被包含在重新渲染中

这是一种可行的方法(在我的示例中,我假设它们是Material-UI组件):

import React from "react";
import {
  Dialog,
  DialogTitle,
  DialogContent,
  DialogContentText,
  DialogActions,
  Button,
  TextField
} from "@material-ui/core";

function CompetencyCheckpoint(props) {
  const [open, setOpen] = React.useState(false);
  const [note, setNote] = React.useState("");

  function updateCheckpoint(note) {
    if (note != null) {
      console.log("Here is our note : " + note);
    } else {
      console.log("oh no, we didn't get the note");
    }
  }
  console.log(note);
  return (
    <div className="checkpoint-container">
      <i className="material-icons" onClick={() => setOpen(true)}>
        note_add
      </i>
      <Dialog open={open} onClose={() => setOpen(false)}>
        <DialogTitle id="form-dialog-title">Add Note</DialogTitle>
        <DialogContent>
          <DialogContentText>Enter a note.</DialogContentText>
          <TextField
            id="filled-textarea"
            label="New Note"
            placeholder="Enter note here"
            multiline
            value={note}
            onChange={e => setNote(e.target.value)}
            margin="normal"
            variant="filled"
            fullWidth
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setOpen(false)} color="primary">
            Cancel
          </Button>
          <Button onClick={() => updateCheckpoint(note)} color="primary">
            Add
          </Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

export default CompetencyCheckpoint;

Edit Dialog

答案 1 :(得分:0)

我能够使代码按预期工作。我不确定,也许这与我使用children:关键字的方式有关,我将检查文档以查看其确切作用。我遵循的是我不完全了解的先例。

这是我想出的解决方案。基本上我只是添加了一个状态变量来控制天气,否则对话框不应该显示。我想这也简化了它,所以我不调用redux来处理对话框切换。

https://codesandbox.io/embed/focused-allen-cg1lq?fontsize=14

通过使Dialog成为其自己的组件,可能还有更多的重构空间。

谢谢大家的帮助,尤其是T.J和Ryan!