Как использовать ловушку useState для установки текста разметки? - PullRequest
0 голосов
/ 29 февраля 2020

У меня есть функциональный компонент со следующим хуком: -

const [imagePreview, setImagePreview] = useState('');

Позже, событие изменения, у меня есть это: -

    if (imagePreviewUrl) {
  setImagePreview( (<div>
    <br/> <img src={imagePreviewUrl} alt="icon" width="200" /> 
    </div>));
}

Похоже, это не так установить что-нибудь. как мне это установить? Я мог бы сделать это так: -

  let imagePreview = null;
if (imagePreviewUrl) {
  imagePreview = (<div>
    <br/> <img src={imagePreviewUrl} alt="icon" width="200" /> 
    </div>);
}

Но это немного уродливо. Я думаю, что useState - рекомендуемый способ сделать это.

Обновление с дополнительным кодом: -

  const fileChangedHandler = event => {
setSelectedFile(event.target.files[0]);
let reader = new FileReader();
reader.onloadend = () => {
setImagePreviewUrl(reader.result);
}
reader.readAsDataURL(event.target.files[0])
if (imagePreviewUrl) {
// can't break into multiline, sytax error 
setImagePreview('(<div><br/> <img src={imagePreviewUrl} alt="icon" width="200" /> </div>)');

}

return (
 <div>
 <label>Profile picture: </label>
  <input className="Column" type="file" accept="image/*" 
       onChange={(e) => {fileChangedHandler(e)}} />
  // I want to show the selected image here as preview before upload 
  { imagePreview }
  </div>
 )

Надеюсь, я дам ясное понимание. Каково мое намерение?

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Причина, по которой у вас возникают проблемы, заключается в том, что вы пытаетесь получить доступ к состоянию imagePreviewUrl сразу после его обновления с помощью setImagePreviewUrl - не будет работать .

const fileChangeHandler = (event) => {
  // ...
  reader.onloadend = () => {
    // this is asynchronous
    // so this definitely wouldn't get
    // executed before you get to the `if` statement below
    // also, `setImagePreviewUrl` is asynchronous as well
    setImagePreviewUrl(reader.result)
  }
  // ...
  if (imagePreviewUrl) {
    // the old value of imagePreviewUrl is being used
    // here, and since the initial value evaluates to 
    // `false`, the `setImagePreview` call below
    // never gets executed
  }
}

Ваше новое значение для imagePreviewUrl не будет доступно сразу, потому что оно асинхронное, поэтому вам, вероятно, следует создать отдельный хук, который прослушивает изменения imagePreviewUrl и обновления imagePreview.

function App() {
  const [imagePreviewUrl, setImagePreviewUrl] = React.useState("");
  const [imagePreview, setImagePreview] = React.useState(null);

  const fileChangedHandler = () => {
    setImagePreviewUrl(
      "https://interactive-examples.mdn.mozilla.net/media/examples/grapefruit-slice-332-332.jpg"
    );
  };

  React.useEffect(() => {
    if (imagePreviewUrl !== "") {
      const image = (
        <div>
          <img alt="fruit" src={imagePreviewUrl} />
        </div>
      );
      setImagePreview(image);
    }
  }, [imagePreviewUrl]);

  return (
    <div className="App">
      <button type="button" onClick={fileChangedHandler}>
        Trigger file change handler.
      </button>
      {imagePreview}
    </div>
  );
}

Вот рабочий пример:

0 голосов
/ 29 февраля 2020

Это не рекомендуемый подход, вам нужен условный рендеринг :

const [imagePreview, setImagePreview] = useState(false);

if (imagePreviewUrl) {
  setImagePreview(true);
}

return (
  imagePreview && (
    <div>
      <br /> <img src={imagePreviewUrl} alt="icon" width="200" />
    </div>
  )
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...