状态更改后不重新呈现的反应

时间:2020-05-06 11:05:58

标签: javascript reactjs

我知道也有类似的问题,但是我有一个奇怪的问题。

这就是我正在做的

import React, {useState} from 'react';
import './App.css';
import {Table, Button, InputGroup, FormControl} from 'react-bootstrap';

function App() {
  const [pons, setPons] = useState();
  const [translations, setTranslations] = useState([]);
  const [isInEditMode, setIsInEditMode] = useState(false);
  const [inputValue, setInputValue] = useState('samochod');
  const [errors, setErrors] = useState([]);
  const [translationsToSave, setTranslationsToSave] = useState([]);

  const changeIsInEditMode = () => setIsInEditMode(!isInEditMode);
  const handleEditButtonClick = (id) => console.log('Edit', id);
  const handleDeleteButtonClick = (id) => console.log('Delete', id);
  const handleInputChange = (e) => setInputValue(e.target.value);
  const handleFetchOnButtonClick = async () => {
    const resp = await fetch(`http://localhost:8080/pons/findTranslation/${inputValue}`).then(r => r.json()).catch(e => console.log(e));
    if (resp.ok === true) {
      setTranslations(resp.resp[0].hits);
      setErrors([]);
    } else {
      setErrors(resp.errors ? resp.errors : ['Something went wrong. check the input']);
    }
  };
  const handleSaveTranslations = async () => {
    const resp = await fetch('localhost:8080/pons/', {method: 'POST', body: {content: translationsToSave}});
    if (resp.ok === true) {
      setInputValue('');
      setTranslations(null);
    }
  };

  return (
    <div className="App">
      {errors.length > 0 ? errors.map(e => <div key={e}>{e}</div>) : null}
      <InputGroup className="mb-3">
        <FormControl
          value={inputValue}
          onChange={handleInputChange}
          placeholder={inputValue}
        />
      </InputGroup>

      <div className="mb-3">
        <Button onClick={handleFetchOnButtonClick} disabled={inputValue === '' || errors.length > 0}>Translate</Button>
        <Button onClick={changeIsInEditMode}>
          {isInEditMode ? 'Exit edit mode' : 'Enter edit mode'}
        </Button>

        <Button disabled={translationsToSave.length === 0} onClick={handleSaveTranslations}>Save translations</Button>
      </div>
      <Table striped bordered hover>
        <thead>
        <tr>
          <th>Original</th>
          <th>Translation</th>
          <th>Actions</th>
        </tr>
        </thead>
        <tbody>
        {translations ? translations.map(pon => pon.roms.map(rom => rom.arabs.map(arab => arab.translations.map(translation => {
          const {source, target} = translation;
          return (
            <tr>
              <td><span dangerouslySetInnerHTML={{__html: source}}/></td>
              <td><span dangerouslySetInnerHTML={{__html: target}}/></td>
              <td>
                {
                  !translationsToSave.includes(target) ?
                    <Button onClick={() => {
                      const tmp = translationsToSave;
                      tmp.push(target);
                      setTranslationsToSave(tmp);
                    }}>
                      Add translation
                    </Button>
                    :
                    <Button
                      onClick={() => {
                        const tmp = translationsToSave;
                        tmp.splice(tmp.findIndex(elem => elem === target));
                        setTranslationsToSave(tmp);
                      }}>
                      Remove translation
                    </Button>
                }
              </td>
            </tr>
          )
        })))) : (
          <div>No translations</div>
        )}
        </tbody>
      </Table>
    </div>
  );
}

export default App;

因此,这是一个基本应用程序,它现在仅在setTranslationsToSave数组中添加和删除。单击Add translation按钮后,视图保持不变。但是当我单击Enter edit mode时它会刷新。与Remove translation相同。我需要单击Enter/Exit edit mode

命中Translate也会重新加载视图。因此,Add/Remove translation按钮是唯一不刷新页面的按钮。为什么?我想念什么?

2 个答案:

答案 0 :(得分:1)

问题是您正在更改“添加/删除”翻译按钮中的卫星,因此在重新渲染之前进行反应检查时,如果状态更新程序被调用为具有相同状态,则感觉没有任何变化,因为它执行了引用检查,并且ehnce不会触发重新渲染

同时根据先前状态更新当前状态时,请使用functional callback approach for state updater

如下更新您的状态

  <Button onClick={() => {
                  setTranslationsToSave(prev => [...prev, target]);
                }}>
                  Add translation
                </Button>
                :
                <Button
                  onClick={() => {

                    setTranslationsToSave((prev) => {
                         const index = prev.findIndex(elem => elem === target));                    return [...prev.slice(0, index), ...prev.slice(index + 1)]
                    });
                  }}>
                  Remove translation
                </Button>

答案 1 :(得分:1)

Add translation点击处理程序中,您正在更改状态:

<Button onClick={() => {
    // tmp is just a reference to state
    const tmp = translationsToSave;
    // You are mutating state, this will be lost
    tmp.push(target);
    setTranslationsToSave(tmp);
}}>

您应该复制状态并添加新元素:

<Button onClick={() => {
    setTranslationsToSave([...translationsToSave, target]);
}}>