레드ux 안 써도 돼요.
다음과 같은 트리 구조를 가정합니다.
여기에 우리는 간단한 삼층나무가 하나 있다.이 트리에서 노드 D와 노드 E는 유사한 데이터를 처리합니다. 만약 사용자가 노드 D에 텍스트를 입력한다면, 우리는 노드 E에 이러한 텍스트를 표시하기를 원합니다.
노드 D에서 노드 E로 데이터를 어떻게 전달합니까?
본고는 이 문제를 해결하는 세 가지 가능한 방법을 소개했다.
방법1: 버팀목 시추
이렇게 하는 방법의 하나는 천진스럽게 데이터를 아이로부터 학부모에게 전달한 다음에 도구를 통해 학부모에게 전달하는 것이다. D->B->A, 그리고 A->C->E
이 아이디어는 하위 노드에서 부 노드로 트리거하는
onUserInput
함수를 사용하여 입력 데이터를 노드 D에서 노드 A로 전송한 다음에 우리는 이 데이터를 노드 A의 상태에서 노드 E로 전달한다.노드 D부터 시작하겠습니다.
class NodeD extends Component {
render() {
return (
<div className="Child element">
<center> D </center>
<textarea
type="text"
value={this.props.inputValue}
onChange={e => this.props.onUserInput(e.target.value)}
/>
</div>
);
}
}
사용자가 내용을 입력할 때 onChange
탐지기는 도구에서 onUserInput
함수를 터치하여 사용자의 입력을 전송합니다.노드 D 아이템 중의 이 기능은 노드 B 아이템 중의 또 다른onUserInput
기능을 촉발한다. 아래와 같다.class NodeB extends Component {
render() {
return (
<div className="Tree element">
<center> B</center>
<NodeD onUserInput={inputValue => this.props.onUserInput(inputValue)} />
</div>
);
}
}
마지막으로 루트 노드 A에 도달했을 때 노드 B 속성에서 터치한 onUserInput
은 노드 A의 상태를 사용자 입력으로 변경합니다.class NodeA extends Component {
state = {
inputValue: ""
};
render() {
return (
<div className="Root element">
<center> A </center>
<NodeB
onUserInput={inputValue => this.setState({ inputValue: inputValue })}
/>
<NodeC inputValue={this.state.inputValue} />
</div>
);
}
}
그런 다음 입력한 값이 아이템을 통해 노드 C에서 해당 하위 노드 E로 전달됩니다.class NodeE extends Component {
render() {
return (
<div className="Child element">
<center> E </center>
{this.props.inputValue}
</div>
);
}
}
보아하니, 그것은 작은 예일지라도 우리의 코드에 복잡성을 증가시켰다.너는 응용 프로그램이 성장할 때 그것이 어떻게 변할지 상상할 수 있니?🤔이런 방법은 나무의 깊이에 의존하기 때문에 더 큰 깊이에 대해 우리는 더 큰 구성 요소층을 통과해야 한다.이것은 너무 길어서 실현할 수 없고, 너무 중복되며, 코드의 복잡성을 증가시킬 수 있다.
메서드 2: Redux 사용
또 다른 방법은 Redux와 같은 주 관리 라이브러리를 사용하는 것이다.
Redux is a predictable state container for JavaScript apps.
The state of our whole application is stored in an object tree within a single store, which your app components depend on. Every component is connected directly to the global store, and the global store life cycle is independent of the components' life cycle.
우선 프로그램의 상태를 정의합니다. 관심 있는 데이터는 사용자가 노드 D에 입력한 데이터입니다. 노드 E가 이 데이터를 사용할 수 있기를 바랍니다. 이를 위해 저희 상점에서 이 데이터를 사용할 수 있습니다.그리고 노드 E는 데이터에 접근하기 위해 그것을 구독할 수 있습니다.
우리는 곧 돌아올 것이다.
1단계: 감속기 정의
다음 단계는 우리의 감속기를 정의하는 것이다.우리의 Reducer는 응용 프로그램의 상태가 저장소로 보내는 작업에 어떻게 응답하는지 지정합니다.감속기 블록은 다음과 같이 정의됩니다.
const initialState = {
inputValue: ""
};
const reducer = (state = initialState, action) => {
if (action.type === "USER_INPUT") {
return {
inputValue: action.inputValue
};
}
return state;
};
사용자가 어떤 내용을 입력하기 전에, Google 상태의 데이터나 inputValue가 빈 문자열임을 알 수 있습니다.따라서, 우리는 빈 문자열인 inputValue로 Reducer의 기본 초기 상태를 정의합니다. The logic here is once the user types something in node D, we "trigger" or rather dispatch an action and our reducer updates the state to whatever has been typed. By "update" here I do not mean "mutate" or change the current state, I do mean return a new state.
if 문장은 형식에 기반한 스케줄링된 동작을 되돌릴 새로운 상태로 비칩니다.그래서 우리는 할당된 조작이 유형 키를 포함하는 대상이라는 것을 이미 알고 있다.우리는 어떻게 새로운 상태의 사용자 입력 값을 얻습니까?우리는 다른 inputValue라는 키를 액션 대상에 추가하기만 하면 됩니다. 우리의 Reducer 블록에서 새로운 상태의 inputValue를 입력값
action.inputValue
을 가지게 합니다.따라서 우리 응용 프로그램의 조작은 다음과 같은 구조를 따를 것이다.{ type: "SOME_TYPE", inputValue: "some_value" }
결과적으로 Dell의 파견 성명은 다음과 같습니다.dispatch({ type: "SOME_TYPE", inputValue: "some_value" })
모든 구성 요소에서 디스패치 문장을 호출할 때, 작업 형식과 사용자 입력 값을 전송합니다.자, 이제 우리는 응용 프로그램의 작업 원리에 대해 하나의 개념을 가지게 되었다. 입력 노드 D에서 우리는
USER_INPUT
유형의 동작을 보내고 사용자가 방금 입력한 모든 내용의 값을 전송한다. 표시 노드 E에서 우리는 응용 프로그램의 현재 상태값, 즉 사용자가 입력한 값을 전송한다. 2단계: 스토어 정의
저희 상점을 사용할 수 있도록,react redux에서 가져온
Provider
구성 요소에 전달합니다.그리고 우리는 응용 프로그램을 그 안에 포장할 것이다.노드 D와 E가 이 저장소의 데이터를 사용할 것을 알고 있기 때문에, 공급자 구성 요소가 이 노드의 공공 부 노드를 포함하기를 원하기 때문에 루트 노드 a 또는 전체 응용 프로그램 구성 요소를 포함합니다.공급업체에 포함할 애플리케이션 구성 요소를 선택하겠습니다.import reducer from "./store/reducer";
import { createStore } from "redux";
import { Provider } from "react-redux";
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
현재 우리는 이미 저장과 감속기를 설치했기 때문에 우리는 노드 D와 E로 손을 더럽힐 수 있다! 3단계: 사용자 입력 논리 구현
먼저 노드 D를 살펴보겠습니다.
textarea
요소에 사용자가 입력한 내용에 관심이 있습니다.이것은 두 가지를 의미한다.1 - 우리는
onChange
이벤트 탐지기를 실현하고 사용자가 저장소에 입력한 모든 내용을 저장해야 한다.2-우리는
textarea
의value 속성을 우리의 저장소에 저장된 값으로 필요로 한다.그러나 이런 일을 하기 전에 우리는 몇 가지 일을 해야 한다.
우리는 우선 노드 D 구성 요소를 우리 상점에 연결해야 한다.이를 위해, 우리는react redux의
connect()
함수를 사용합니다.연결된 구성 요소에 저장에 필요한 데이터 세션과 저장에 할당할 수 있는 함수를 제공합니다. This is why we use the two
mapStateToProps
andmapDispatchToProps
which deal with the store's state and dispatch respectively. We want our node D component to be subscribed to our store updates, as in, our app's state updates. This means that any time the app's state is updated,mapStateToProps
will be called. The results ofmapStateToProps
is an object which will be merged into our node D's component props. OurmapDispatchToProps
function lets us create functions that dispatch when called, and pass those functions as props to our component. We will make use of this by returning new function that callsdispatch()
which passes in an action.
우리의 예에서
mapStateToProps
함수에 대해 우리는 inputValue에만 관심이 있기 때문에 우리는 하나의 대상{ inputValue: state.inputValue }
으로 돌아간다.mapDispatchToProps
에 대해 우리는 함수onUserInput
를 되돌려줍니다. 이 함수는 입력 값을 매개 변수로 하고 이 값을 사용하여 유형USER_INPUT
의 조작을 보냅니다.mapStateToProps
되돌아오는 새로운 상태 대상과 onUserInput
함수가 우리 구성 요소의props에 통합됩니다.따라서 Dell의 구성 요소는 다음과 같이 정의됩니다.class NodeD extends Component {
render() {
return (
<div className="Child element">
<center> D </center>
<textarea
type="text"
value={this.props.inputValue}
onChange={e => this.props.onUserInput(e.target.value)}
/>
</div>
);
}
}
const mapStateToProps = state => {
return {
inputValue: state.inputValue
};
};
const mapDispatchToProps = dispatch => {
return {
onUserInput: inputValue =>
dispatch({ type: "USER_INPUT", inputValue: inputValue })
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(NodeD);
우리 노드 D 끝났어!이제 노드 E로 이동합니다. 사용자 입력을 표시하려고 합니다. 4단계: 사용자 출력 논리 구현
우리는 이 노드에 사용자 입력 데이터를 표시하기를 희망합니다.우리는 이러한 데이터가 기본적으로 우리 응용 프로그램의 현재 상태, 예를 들어 우리 상점의 현재 상태라는 것을 이미 알고 있다.그래서 최종적으로 우리는 이 저장소를 방문하여 그 데이터를 표시하기를 희망한다.이를 위해, 우리는 우선
connect()
함수와 이전에 사용한 mapStateToProps
함수를 사용하여 노드 E 구성 요소를 구독하여 상점의 업데이트를 받아야 합니다.그 후에, 우리는 그것을 사용하여 구성 요소의 도구로부터 저장된 데이터에 접근할 수 있다.도구.val 자체:class NodeE extends Component {
render() {
return (
<div className="Child element">
<center> E </center>
{this.props.val}
</div>
);
}
}
const mapStateToProps = state => {
return {
val: state.inputValue
};
};
export default connect(mapStateToProps)(NodeE);
저희가 드디어 레드ux를 완성했습니다!🎉 너는 우리가 방금 무엇을 했는지 볼 수 있다here.더 복잡한 예에서, 예를 들어 나무가 더 많은 공유/조작 저장소를 포함하는 구성 요소를 포함하기 때문에, 우리는 모든 구성 요소에 이 두 개
mapStateToProps
와 mapDispatchToProps
함수를 사용해야 한다.이러한 상황에서 모든 구성 요소에 단독 폴더를 만들어서 우리의 조작 유형과 간소화 프로그램을 구성 요소와 분리하는 것이 현명할 수 있습니다. 누가 시간을 맞췄습니까?
방법 3: React의 컨텍스트 API 사용
이제 컨텍스트 API를 사용하여 동일한 예를 다시 작성합니다.
리액트Context API는 한동안 존재해 왔지만 리액트의 버전16.3.0은 생산에서 안전하게 사용되고 있다.이 논리는 Redux의 논리와 매우 가깝다. 우리는 상하문 대상이 있는데, 그 중에는 우리가 다른 구성 요소에서 접근하고자 하는 전역 데이터가 포함되어 있다.
우선, 프로그램의 초기 상태를 기본 상태로 포함하는 상하문 대상을 만듭니다.그런 다음
Provider
구성 요소 하나Consumer
를 생성합니다.const initialState = {
inputValue: ""
};
const Context = React.createContext(initialState);
export const Provider = Context.Provider;
export const Consumer = Context.Consumer;
Our
Provider
component has as children all the components from which we want to access the context data. Like theProvider
from the Redux version above. To extract or manipulate the context, we use our Consumer component which represents the component.
우리는
Provider
구성 요소가 위의 Redux 버전과 같이 전체 응용 프로그램을 포장하기를 희망합니다.그러나 이것Provider
은 우리가 이전에 본 것과 약간 다르다.응용 프로그램 구성 요소에서 기본 상태를 초기화합니다. Provider
구성 요소를 통해 이 데이터를 공유할 수 있습니다. 우리의 예에서 우리는 이 점을 나누었다.주 정부.inputValue 및 onUserInput 함수와 같은 조종 상태의 함수
class App extends React.Component {
state = {
inputValue: ""
};
onUserInput = newVal => {
this.setState({ inputValue: newVal });
};
render() {
return (
<Provider
value={{ val: this.state.inputValue, onUserInput: this.onUserInput }}
>
<div className="App">
<NodeA />
</div>
</Provider>
);
}
}
현재 우리는 우리의 소비자 구성 요소 접근Provider
구성 요소의 데이터를 계속 사용할 수 있다:사용자가 데이터를 입력한 노드 D의 경우:
const NodeD = () => {
return (
<div className="Child element">
<center> D </center>
<Consumer>
{({ val, onUserInput }) => (
<textarea
type="text"
value={val}
onChange={e => onUserInput(e.target.value)}
/>
)}
</Consumer>
</div>
);
};
사용자가 입력한 노드 E를 표시하는 경우:const NodeE = () => {
return (
<div className="Child element ">
<center> E </center>
<Consumer>{context => <p>{context.val}</p>}</Consumer>
</div>
);
};
우리는 이미 예시된 상하문 버전을 완성했다.🎉 그렇게 어렵지 않죠?보기here만약 우리가 더 많은 구성 요소가 상하문에 접근하기를 희망한다면?우리는 Provider 구성 요소로 그것들을 포장한 다음에Consumer 구성 요소로 상하문에 접근/조작할 수 있습니다!단순성:)
네, 그런데 어느 것을 써야 하나요?
우리의 예시 Redux 버전이 상하문 버전보다 더 많은 시간을 들였다는 것을 알 수 있습니다.이제 Redux를 볼 수 있습니다.
복잡성 증가: 많은 구성 요소를 처리할 때 감속기와 동작 유형을 구성 요소에서 유일한 폴더/파일로 분리하는 것이 현명할 수 있습니다.
그러나 구성 요소에서 접근할 수 있도록 데이터만 글로벌화하려면, Redux와 React의 상하문 API가 대체적으로 같은 일을 한 것을 예시로 볼 수 있습니다.그래서 어느 정도는 레드ux를 사용할 필요가 없어요!
Reference
이 문제에 관하여(레드ux 안 써도 돼요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/anssamghezala/you-don-t-have-to-use-redux-32a6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)