Как я могу динамически изменять изображение в Ionic React?

#reactjs #ionic-react

#reactjs #ionic-react

Вопрос:

Я довольно новичок в React и TypeScript, и я столкнулся с этой проблемой:

В моем пользовательском интерфейсе я использую несколько декоративных графических элементов следующим образом:

 import Kitten from './img/Kitten.png';
<img className="Image" src={Kitten} />
  

Теперь у меня есть переключатель темного режима. Когда он срабатывает, я хочу заменить все изображения их соответствующей версией в темном режиме. Я думал о чем-то подобном:

 import Kitten from './img/Kitten.png';
import DarkKitten from './img/DarkKitten.png';

//gets called when dark mode is toggled on or off
const darkModeToggleFunc = () => {
  document.querySelectorAll('.Image').forEach(element => {
    if(element.src.includes("Dark")) {
      element.src = element.src.replace("Dark", "");
    } else{
      element.src = "Dark"   element.src;
    }
  });
}

<img className="Image" src={Kitten} />
  

Теперь, в React у меня есть две проблемы: атрибут .src неизвестен, потому element что не обязательно является изображением, и вторая проблема: я не назначаю URI как src, а переменную из импорта. Так что на самом деле нет ни одной строки, которую я мог бы изменить… Если я правильно информирован, React использует Base64 для изображений, указанных таким образом.

Как я мог бы достичь своей цели в React?

Редактировать: App.tsx

 //bunch of imports
const App: React.FC = () => {

  return (
    <IonApp>
      <IonReactRouter>
        <IonSplitPane contentId="main">
          <Menu />
          <IonRouterOutlet id="main">
            <Route path="/page/:name" component={Page} exact />
            <Redirect from="/" to="/page/Production" exact />
          </IonRouterOutlet>
        </IonSplitPane>
      </IonReactRouter>
    </IonApp>
  );
};

export default App;
  

Комментарии:

1. Могу ли я спросить, почему это помечено react-native при работе с элементами html? В любом случае, даже если вы хотите сделать это в react-native, реализация должна быть довольно похожей, но в случае, если это так, пожалуйста, создайте для этого отдельный вопрос. На данный момент я удалил тег.

Ответ №1:

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

Ваш сценарий связан с изменением темы приложения, этот ответ касается использования контекста реакции для изменения темы и надлежащего использования изображений.

Сначала вы создаете контекст, который будет содержать значение темы

 const AppContext = createContext({
  theme: "light",
  setTheme: (theme) => {}
});
  

Здесь мы будем использовать переменную состояния для простоты, вы можете использовать все, что вам больше нравится.
Вот app.js файл

 export default function App() {
  const [theme, setTheme] = React.useState("light");

  const themeState = { theme, setTheme };

  return (
    <AppContext.Provider value={themeState}>
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <ImageViewer />
        <DarkModeSwitch />
      </div>
    </AppContext.Provider>
  );
}
  

Здесь мы устанавливаем значение темы в состояние и устанавливаем контекст для этого, setTheme можно использовать для обновления темы из любого компонента, который находится в дереве. в вашем случае darkmodeswitch, здесь мы переключаем значение

 const DarkModeSwitch = () => {
  const { theme, setTheme } = useContext(AppContext);

  const darkModeToggle = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <div>
      <input
        type="checkbox"
        checked={theme === "light"}
        onChange={() => darkModeToggle()}
      />
    </div>
  );
};
  

Переходя к вашему основному требованию, изображениям, давайте использовать общие файлы для изображений с содержимым

 export const Kitten ="image source 1";
export const KittenDark ="image source 2";
  

Вы просто устанавливаете изображение на основе темы, как показано ниже

 import { Kitten, KittenDark } from "./images";

export default function ImageViewer() {
  const { theme } = useContext(AppContext);

  return (
    <img
      alt="kitten"
      style={{ height: 50, width: 100 }}
      src={theme === "light" ? Kitten : KittenDark}
    />
  );
}
  

как вы можете видеть, все связано через контекст, и как только вы обновите контекст, вы увидите, что изображения меняются.
Вы можете увидеть рабочую версию здесь
https://codesandbox.io/s/react-theme-switch-3hvbg

Это не «ПРАВИЛЬНЫЙ» способ, это один из способов обработки требований, вы можете использовать такие вещи, как redux и т. Д

Комментарии:

1. Я не согласен с заключительной частью вашего ответа, в то время как redux имеет свою полезность в определенных случаях, это не один из них, и установка нового пакета для того, что может быть элегантно обработано контекстом react, совершенно не нужна. В любом случае вы получили от меня 1.

2. Ну, это правда, но если он уже использует redux, он может его использовать, я родом из мира react-native, и у меня был вариант сохранения состояния redux, поэтому что-то вроде темы было бы полезно, большое спасибо за поддержку 🙂

3. Прежде всего, большое вам спасибо за этот подробный ответ! Я очень ценю подобные объяснения, чтобы я мог учиться. Я в пути, поэтому позже я сопоставлю ваш код с моим проектом, и если все сработает, я, конечно, отмечу ваш ответ 🙂

4. Итак, я вернулся домой. Во-первых, я застрял с кодом, который вы предоставили для файла app.js / tsx. Я добавил свой в свой исходный пост, не могли бы вы указать, как интегрировать ваш фрагмент?

5. у вас может быть состояние в app.js нравится мой образец и есть Контекст. Поставщик для переноса других компонентов