包子!
包子!
发布于 2025-02-06 / 13 阅读 / 0 评论 / 0 点赞

【React->Solidjs】四、实战:Todo应用迁移 🛠️

1. 项目初始化

# React版本(使用CRA)
npx create-react-app todo-react --template typescript

# SolidJS版本(使用Vite)
npm init vite@latest todo-solid -- --template solid-ts

目录结构对比

React项目
├── src
│   ├── components
│   ├── redux (状态管理)
│   └── App.tsx

Solid项目
├── src
│   ├── components
│   ├── stores (响应式存储)
│   └── App.tsx

2. 状态层改造

React版本(Redux)

// redux/slice.ts
interface TodoState {
  todos: { id: string; text: string; done: boolean }[]
}

export const todoSlice = createSlice({
  name: 'todos',
  initialState: { todos: [] },
  reducers: {
    addTodo: (state, action) => {
      state.todos.push(action.payload)
    },
    toggleTodo: (state, action) => {
      const todo = state.todos.find(t => t.id === action.payload)
      if (todo) todo.done = !todo.done
    }
  }
})

SolidJS版本(createStore)

// stores/todo.ts
export const [todoStore, setTodoStore] = createStore({
  todos: [] as TodoItem[]
})

export const addTodo = (text: string) => {
  setTodoStore('todos', (prev) => [
    ...prev,
    { id: crypto.randomUUID(), text, done: false }
  ])
}

export const toggleTodo = (id: string) => {
  setTodoStore('todos', 
    (t) => t.id === id,
    'done',
    (done) => !done
  )
}

核心差异

  • 无需Redux的useSelector/useDispatch

  • 支持路径语法直接修改嵌套状态

  • 自动响应式更新相关组件

3. 组件改造

Todo列表组件对比

// React版本
const TodoList = () => {
  const todos = useSelector(state => state.todos)
  
  return (
    <ul>
      {todos.map(todo => (
        <TodoItem key={todo.id} todo={todo} />
      ))}
    </ul>
  )
}

// SolidJS版本
const TodoList = () => {
  return (
    <ul>
      <For each={todoStore.todos}>
        {(todo) => <TodoItem todo={todo} />}
      </For>
    </ul>
  )
}

事件处理优化

// React需要手动绑定事件参数
<button onClick={() => onToggle(todo.id)}>Toggle</button>

// SolidJS利用事件代理优化
<button onClick={[onToggle, todo.id]}>Toggle</button>

4. 性能优化实践

组件拆分策略

// 低效写法(整个列表重新渲染)
const TodoList = () => {
  // 访问整个store会导致任何修改都触发更新
  return <For each={todoStore.todos}>...</For>
}

// 高效写法(细粒度组件)
const TodoList = () => {
  // 只传递数组引用
  const todos = todoStore.todos
  
  return (
    <For each={todos}>
      {(todo) => <TodoItem todo={todo} />}
    </For>
  )
}

const TodoItem = (props: { todo: TodoItem }) => {
  // 每个Item独立响应自己的todo变化
  return <li>{props.todo.text}</li>
}

服务端渲染预配置

// vite.config.js
import solid from 'vite-plugin-solid'

export default defineConfig({
  plugins: [
    solid({ 
      ssr: true // 启用SSR支持
    })
  ]
})

🔧 迁移工具推荐

  1. Babel插件@solid-soda/transform 可自动转换部分React语法

  2. Eslint规则eslint-plugin-solid 检测响应式误用

  3. Chrome扩展:Solid DevTools 可视化组件依赖关系

// 错误模式检测示例
function BadComponent(props) {
  // eslint会警告props解构问题
  const { user } = props
  
  return <div>{user.name}</div> // ❌ 失去响应性
}


评论