LINUX.ORG.RU

Нужна помощь по React

 ,


0

1

Всем привет. Такое дело. Решил написать приложение погоды на React. Захотелось сделать его прямо-таки компонентным. Чтобы каждая функция, была отдельным файлом JSX. Столкнулся с такой проблемой: Написал функцию, которая принемает введённые пользователем данные в поле ввода, но вот вопрос. Запихал это дело в state через useState, Но вот вопрос, как мне теперь юзать то, что я получил в других функциях. Я импортирую функцию, но вот как быть дальше - хз. Потому как, как принять это самое состояние, не имею понятия. (Да, я понимаю, что можно заюзать пропсы, но вот КАК ИМЕННО их юзать в данной ситуации - не знаю.) Вот код функции.

import React from 'react';
import styled from 'styled-components';
import { useState } from 'react';

const Input = styled.input background: transparent; color: #fff; &focus { outline: none; };;

const Button = styled.button background: transparent; color: #fff; border: none;;

export default function GetCity(props) {
let [city, setCity] = useState('')

function getEvent(event) {
    setCity(event.target.value);
};
return (
<>

<Button onClick={() => props.onClick(city)}>Найти город

</>
)
}


Последнее исправление: hobbit (всего исправлений: 1)

Но вот вопрос, как мне теперь юзать то, что я получил в других функциях

Через глобальный стейт, варианты:

  • модно-молодёжно через Context.Provider и useContext вместе с useReducer
  • ну и старая классика в виде Redux
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)

Если есть вложенные компоненты которым нужно передать переменную от родителя, то используй useContext:

https://react.dev/reference/react/useContext

Но через Context можно передать только одну переменную, если ничего не изменилось в API.

Ну и props:

https://react.dev/learn#sharing-data-between-components

axle_nix ★★
()

Вот пример глобального стейта на хуках в redux-стиле. Глобальный счётчик меняется в компоненте CounterBoost и доступен всем остальным (в данном случае компоненту CounterView) через контекст.

App.jsx:

import { Store } from './store';

import CounterBoost from './counter';
import CounterView from './counterView';

const App = () => (
  <Store>
    <div className="App">
      <CounterView />
      <CounterBoost />
    </div>
  </Store>
);

export default App

store.jsx:

import React, { createContext, useReducer } from 'react';

const initialState = {
    count: 0,
};

const Reducer = (state, action) => {
  switch (action.type) {
    case "SET_COUNT":
        return {
            ...state,
            count: action.count,
        };
    default:
        return state;
  }
};

export const StoreContext = createContext(initialState);

export const Store = ({children}) => {
    const [state, dispatch] = useReducer(Reducer, initialState);
    return (
        <StoreContext.Provider value={[state, dispatch]}>
            {children}
        </StoreContext.Provider>
    )
};

counterView.jsx:

import { useContext } from 'react';
import { StoreContext } from './store';


const CounterView = () => {
  const [state, dispatch ] = useContext(StoreContext);
  return (
    <div>
      {`count is ${state.count}`}
    </div>
  );
}

export default CounterView;

counter.jsx:

import { useContext } from 'react';
import { StoreContext } from './store';

const CounterBoost = () => {
  const [ state, dispatch ] = useContext(StoreContext);
  const boost = () => {
    dispatch({type: 'SET_COUNT', count: state.count + 1});
  }
  return (
    <button onClick={boost}>
      Boost me
    </button>
  );
}

export default CounterBoost;
vvn_black ★★★★★
()

Пример в парадигме только контекста и провайдера.

App.jsx:

import { StoreProvider } from './context';

import CounterBoost from './counter';
import CounterView from './counterView';

const App = () => (
  <StoreProvider>
    <div className="App">
      <CounterView />
      <CounterBoost />
    </div>
  </StoreProvider>
);

export default App

context.jsx:

import { createContext, useContext, useState } from 'react';

const StoreContext = createContext();

const useStore = () => {
  return useContext(StoreContext);
}

const StoreProvider = ({ children  }) => {

  const store = ProvideStore();

  return (
    <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
  );
}

const ProvideStore = () => {
  const [count, setCount] = useState(0);
  const boostCount = () => {
    setCount(prevCount => prevCount + 1);
  }

  return {count, boostCount}
}

export {useStore, StoreProvider};

counterView.jsx:

import { useStore } from './context';

const CounterView = () => {
  const { count } = useStore();
  return (
    <div>
      {`count is ${count}`}
    </div>
  );
}

export default CounterView;

counter.jsx:

import { useContext } from 'react';
import { useStore } from './context';

const CounterBoost = () => {
  const { boostCount } = useStore();
  return (
    <button onClick={boostCount}>
      Boost me
    </button>
  );
}

export default CounterBoost;
vvn_black ★★★★★
()

можно определить функцию useController в файле controller.ts внутри которого засунуть этот стейт и в return контроллера его прописать и затем использовать в компонентах примерно так:

geoCityController.ts:

type Props = {
..optional props
};

export function useGeoCityController(props: Props) {

 let { ..optioal props } = props;

 let [city, setCity] = useState('')

 return {
   city,
   setCity,
 }
}

any jsx:

export default function GetCity(props) {
  let { city, setCity } = useGeoCityController({ optioal props ..});  
  return (<div>city</div>);
}

а если есть возможность выбирать, используй лучше CustomElements из стандартов Web Components для компонентной организации фронтенд кода, они просты и элегантны и работают в любом современном бравзере без транспиляторов и библиотек. Для межкомпонентного взаимодействия там можно использовать браузерные эвенты Custom Events или инжектить сервисные классы, на хабре я писал статью про это.

Syncro ★★★★★
()
Последнее исправление: Syncro (всего исправлений: 3)
Ответ на: комментарий от static_lab

я их не готовлю специально, из того что помню:

  1. может в рантайме не увидеть значение т.е. оно будет каким-нибудь андефайнд или нулом и заманаешься потом искать в чем там ошибка

  2. если использовать объекты ряктового жц внутри своих замечательных классов и методов, то могут вылазить рантайм ошибки вида: «используйте шнягу только внутри кусков рякта»

Syncro ★★★★★
()
Ответ на: комментарий от static_lab

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

Syncro ★★★★★
()