Skip to content

Commit e1ca094

Browse files
committed
chore: redux compatibility test
1 parent af37c4e commit e1ca094

File tree

11 files changed

+1034
-0
lines changed

11 files changed

+1034
-0
lines changed

packages/redux-tester/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# openinula + vite
2+
3+
该模板提供了 `openinula` 工作在 `vite`的基础配置。
4+
> 请注意由于Vite插件有node版本限制,请使用`node -v`命令确认node版本大于等于node v18。

packages/redux-tester/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>My Inula App</title>
6+
</head>
7+
<body>
8+
<div id="root"></div>
9+
<script type="module" src="/src/index.jsx"></script>
10+
</body>
11+
</html>

packages/redux-tester/package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "inula-vite-app",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "vite",
8+
"build": "vite build"
9+
},
10+
"keywords": [],
11+
"author": "",
12+
"license": "MulanPSL2",
13+
"dependencies": {
14+
"@reduxjs/toolkit": "^2.9.0",
15+
"openinula": "https://pkg.pr.new/openInula/inula/openinula@64",
16+
"react-redux": "^9.0.0"
17+
},
18+
"devDependencies": {
19+
"@babel/core": "^7.21.4",
20+
"@babel/preset-env": "^7.21.4",
21+
"@babel/preset-react": "^7.18.6",
22+
"@vitejs/plugin-react": "^3.1.0",
23+
"@vitejs/plugin-react-refresh": "^1.3.6",
24+
"babel-plugin-import": "^1.13.6",
25+
"vite": "^4.2.1"
26+
}
27+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useSelector, useDispatch } from 'react-redux';
2+
import { increment, decrement, incrementByAmount, reset, clearHistory, selectCounter, selectCounterHistory } from '../store';
3+
4+
function Counter() {
5+
const count = useSelector(selectCounter);
6+
const history = useSelector(selectCounterHistory);
7+
const dispatch = useDispatch();
8+
9+
return (
10+
<div className="counter-container">
11+
<h2>Counter Test Component</h2>
12+
<div className="counter-display">
13+
<h3>Count: {count}</h3>
14+
</div>
15+
<div className="counter-buttons">
16+
<button onClick={() => dispatch(increment())}>
17+
+1
18+
</button>
19+
<button onClick={() => dispatch(decrement())}>
20+
-1
21+
</button>
22+
<button onClick={() => dispatch(incrementByAmount(5))}>
23+
+5
24+
</button>
25+
<button onClick={() => dispatch(reset())}>
26+
Reset
27+
</button>
28+
</div>
29+
<div className="counter-history">
30+
<h4>History:</h4>
31+
<button onClick={() => dispatch(clearHistory())}>
32+
Clear History
33+
</button>
34+
<ul>
35+
{history.map((entry, index) => (
36+
<li key={index}>{entry}</li>
37+
))}
38+
</ul>
39+
</div>
40+
</div>
41+
);
42+
}
43+
44+
export default Counter;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { useSelector, useDispatch, useStore } from 'react-redux';
2+
import { useCallback, useMemo } from 'react';
3+
import { selectCounter, selectTodos, increment } from '../store';
4+
5+
function ReduxCompatibilityTest() {
6+
const dispatch = useDispatch();
7+
const store = useStore();
8+
9+
const count = useSelector(selectCounter);
10+
const todos = useSelector(selectTodos);
11+
12+
const memoizedCount = useSelector(useCallback(state => state.counter.value, []));
13+
14+
const computedStats = useMemo(() => {
15+
return {
16+
totalTodos: todos.length,
17+
completedTodos: todos.filter(todo => todo.completed).length,
18+
countDoubled: count * 2
19+
};
20+
}, [todos, count]);
21+
22+
const testBatchedUpdates = () => {
23+
dispatch(increment());
24+
dispatch(increment());
25+
dispatch(increment());
26+
};
27+
28+
return (
29+
<div className="compatibility-test">
30+
<h2>React-Redux Compatibility Test</h2>
31+
32+
<div className="test-section">
33+
<h3>Hook Tests</h3>
34+
<p><strong>useSelector:</strong> ✅ Count: {count}</p>
35+
<p><strong>useSelector (memoized):</strong> ✅ Count: {memoizedCount}</p>
36+
<p><strong>useDispatch:</strong> ✅ Available</p>
37+
<p><strong>useStore:</strong> ✅ Store available: {store ? 'Yes' : 'No'}</p>
38+
</div>
39+
40+
<div className="test-section">
41+
<h3>Computed Values (useMemo)</h3>
42+
<p>Total Todos: {computedStats.totalTodos}</p>
43+
<p>Completed Todos: {computedStats.completedTodos}</p>
44+
<p>Count Doubled: {computedStats.countDoubled}</p>
45+
</div>
46+
47+
<div className="test-section">
48+
<h3>Batched Updates Test</h3>
49+
<button onClick={testBatchedUpdates}>
50+
Dispatch 3 increments (should batch)
51+
</button>
52+
<p>Current count: {count}</p>
53+
</div>
54+
55+
<div className="test-section">
56+
<h3>Store State Inspection</h3>
57+
<pre style={{ fontSize: '12px', background: '#f5f5f5', padding: '10px' }}>
58+
{JSON.stringify(store?.getState(), null, 2)}
59+
</pre>
60+
</div>
61+
</div>
62+
);
63+
}
64+
65+
export default ReduxCompatibilityTest;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useState } from 'react';
2+
import { useSelector, useDispatch } from 'react-redux';
3+
import { addTodo, toggleTodo, removeTodo, setFilter, selectFilteredTodos, selectTodosFilter } from '../store';
4+
5+
function TodoList() {
6+
const todos = useSelector(selectFilteredTodos);
7+
const filter = useSelector(selectTodosFilter);
8+
const dispatch = useDispatch();
9+
const [inputText, setInputText] = useState('');
10+
11+
const handleSubmit = (e) => {
12+
e.preventDefault();
13+
if (inputText.trim()) {
14+
dispatch(addTodo(inputText.trim()));
15+
setInputText('');
16+
}
17+
};
18+
19+
return (
20+
<div className="todo-container">
21+
<h2>Todo List Test Component</h2>
22+
23+
<form onSubmit={handleSubmit}>
24+
<input
25+
type="text"
26+
value={inputText}
27+
onChange={(e) => setInputText(e.target.value)}
28+
placeholder="Add a todo..."
29+
/>
30+
<button type="submit">Add</button>
31+
</form>
32+
33+
<div className="filter-buttons">
34+
<button
35+
className={filter === 'all' ? 'active' : ''}
36+
onClick={() => dispatch(setFilter('all'))}
37+
>
38+
All
39+
</button>
40+
<button
41+
className={filter === 'active' ? 'active' : ''}
42+
onClick={() => dispatch(setFilter('active'))}
43+
>
44+
Active
45+
</button>
46+
<button
47+
className={filter === 'completed' ? 'active' : ''}
48+
onClick={() => dispatch(setFilter('completed'))}
49+
>
50+
Completed
51+
</button>
52+
</div>
53+
54+
<ul className="todo-list">
55+
{todos.map(todo => (
56+
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
57+
<input
58+
type="checkbox"
59+
checked={todo.completed}
60+
onChange={() => dispatch(toggleTodo(todo.id))}
61+
/>
62+
<span>{todo.text}</span>
63+
<button onClick={() => dispatch(removeTodo(todo.id))}>
64+
Delete
65+
</button>
66+
</li>
67+
))}
68+
</ul>
69+
</div>
70+
);
71+
}
72+
73+
export default TodoList;

0 commit comments

Comments
 (0)