输入文字-'defaultValue'未加载状态值,并且'value'在更改时未更新

时间:2020-05-09 08:38:30

标签: javascript reactjs typescript react-redux react-hooks

我的输入文本如下( MovieInput.tsx ):

<input 
    id="inputMovieTitle" 
    type="text"
    onChange={ e => titleHandleChange(e) }
    value={ getTitle() }>
</input>

titleHandleChange:

const [title, setTitle] = useState('');

const titleHandleChange = (e: ChangeEvent<HTMLInputElement>) => {        
    setTitle(e.target.value);
}

getTitle:

const moviesInState = useSelector((state: any) => state.movies);

const getTitle = () => {      
    console.log(moviesInState.item.title); // It displays correct movie title from the store corresponding to the selected row
    return moviesInState.item.title;
}

我有一个表格(Grid.tsx),其中列出了该州的所有电影(state.movi​​es.items [])。当我单击该表中的任何电影行时,所选电影将在商店中更新,即state.movi​​es.item。

Grid.tsx:

const dispatch = useDispatch();

const selectMovie = (movie: Movie) => {
    const movieSelected: Movie = {
        _id: movie._id,
        __v: movie.__v,
        title: movie.title,
        rating: movie.rating,
        year: movie.year
    }
    dispatch(getMovie(movieSelected));
}
...
<tbody>
    {
        props.allMovies.map((movie: Movie) => 
            <tr onClick={() => selectMovie(movie)}>
                <td>{movie.title}</td>
                <td>{(+movie.rating).toFixed(1)}</td>
                <td>{movie.year}</td>
            </tr>
        )
    }
</tbody>

现在,当我单击表(Grid.tsx)中的任何行时,它将更新商店中的store.movi​​es.item,并且文本输入(在MovieInput.tsx中)将显示所选电影的标题。当我更改选定的行时,文本输入的值也会更新。

为什么要在文本输入中加载所选电影的标题文本?

因为,我应该能够编辑标题值并更新DB中的记录。我选择任何行,更改其标题,然后单击“更新”按钮并保存。但是,尽管在输入中成功填充了文本并在我们更改所选行时正确地进行了更改,但文本输入仍然是“不可编辑的”。这是由于以下代码:

value={ getTitle() }>

当我按如下方式将'value'更改为'defaultValue'时,我可以编辑文本输入,但是这次,当我选择另一行时,文本值没有改变。

defaultValue={ getTitle() }>

它工作得很好,并显示更新的值(当我更改选定的行时),直到我编辑输入。首次编辑后,不会在另一行单击上更改其值。仅保留编辑后的文本,但是我希望在选择另一行时该值会发生变化。但是,getTitle()函数中的控制台日志会显示与所选行相对应的商店(store.movi​​es.item)中正确的标题。

能否让我知道如何执行以下操作?

  • 使文本输入可编辑
  • 使文本输入在更改选定的行后更改其值(即使在编辑输入之前,输入也应丢失编辑并更改为新值)

1 个答案:

答案 0 :(得分:1)

更改后输入不显示更新后的值的原因是因为它通过moviesInState绑定到redux存储中的值。

据我所见,您希望输入的初始值来自getTitle(),而输入的更新值应来自用户键入的任何内容。

因此,您应该更改的第一件事是使用商店中的值设置title状态的初始值。

const moviesInState = useSelector((state: any) => state.movies);
const getTitle = () => {      
    console.log(moviesInState.item.title); // It displays correct movie title from the store corresponding to the selected row
    return moviesInState.item.title;
}
const [title, setTitle] = useState(getTitle());

鉴于必须在更新商店时更新输入,因此需要useEffect钩子来传播状态更新。

useEffect(() => {
  if (moviesInState.item.title !== title) {
    setTitle(moviesInState.item.title);
  }
}, [moviesInState]);

接下来,将title状态绑定到value的{​​{1}}道具。 input方法没有问题,因此我们可以保持现状。另外,不需要依赖titleHandleChange,因此我们可以删除它的用法。

defaultValue

另一方面,您不应使用<input id="inputMovieTitle" type="text" onChange={titleHandleChange} value={title}> </input> ,因为这将消除TypeScript的类型检查功能的优点。相反,您应该将any参数定义为为redux存储定义的根状态类型。例如,

state