useState 钩子不更新值

Twi*_*geh 5 javascript jsx reactjs

我是新手,我不明白为什么h1 标签内的标题会更新,但图像组件内的url没有?

列表组件

import React, { useState, useEffect, useContext } from 'react';
import Image from './Image';
import Size from '../index';

export default function Listing(props) {
  const [title, setTitle] = useState(props.title);
  const [url, setUrl] = useState(props.url);

  const value = useContext(Size);

  return (
    <div>
      <Image url={url} size={value.size} />

      <h1>{title}</h1>
      <form>
        <input id='URL' type='text' />
        <button
          onClick={e => {
            e.preventDefault();
            setUrl(document.getElementById('URL').value);
            setTitle(document.getElementById('URL').value);
          }}
        >
          Submit
        </button>
      </form>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的猜测是,如果 prop 发生变化,React 不会更新子组件,但是我该如何手动更新呢?

图像组件

import React from 'react';

export default class Image extends React.Component {
  //console.log(props.size);
  constructor(props) {
    super(props);
    this.url = props.url;
    this.size = props.size;
  }
  render() {
    return <img src={this.url} style={{ height: this.size + 'px' }} alt='' />;
  }
}```
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 3

您的代码有很多“味道”。这是简短、快速的答案:

将其更改src={this.url}为:src={this.props.url}

图像从未更新的原因是:

constructor(props) {
  super(props);
  this.url = props.url;
  this.size = props.size;
}
Run Code Online (Sandbox Code Playgroud)

您正在将局部变量设置为初始 prop 值。由于您在构造函数中设置了这些内容,因此这些行只会在创建组件时执行,而不会在发送新道具时执行。React 仍会触发重新渲染,因为您正在发送新道具,但新值永远不会被使用,因此旧结果会保留。


稍微长一点的答案:

像这里一样直接混合从 DOM 读取的值并不是一个好主意:

setUrl(document.getElementById('URL').value);
setTitle(document.getElementById('URL').value);
Run Code Online (Sandbox Code Playgroud)

相反,有 2 个状态。一个保存输入的当前值,每次击键都会更新,另一个保存您发送到图像组件的值。

也许是这样的:

export default function Listing(props) {
  const [title, setTitle] = useState(props.title);
  const [inputUrl, setInputUrl] = useState(props.url);
  const [url, setUrl] = useState(props.url);

  const value = useContext(Size);

  return (
    <div>
      <Image url={url} size={value.size} />

      <h1>{title}</h1>
      <form>
        <input
          value={inputUrl}
          onChange={e => setInputUrl(e.target.value)}
        />
        <button
          type="button"
          onClick={() => {
            setUrl(inputUrl);
            setTitle(inputUrl);
          }}
        >
          Submit
        </button>
      </form>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

另请注意,我删除e.preventDefault()并添加type="button"到您的按钮,因为默认类型是submit,这可能会刷新您的页面。